synchronized如何实现的以及什么是锁升级volatile的特点Java中的指令重排悲观锁与乐观锁区别什么是CAS什么是ThreadLocalNIO、BIO、AIO区别有哪些缓冲流序列化OSI网络模型TCP与UDP区别TCP三次握手与四次挥手GET与POST区别
synchronized如何实现的以及什么是锁升级
JDK1.8中对synchronized做了优化,提供了三种不同状态时的锁,分别是偏向锁、轻量级、重量级锁。
所谓的锁的升级与降级,其实就是jvm对synchronized所做的一种优化,jvm会检测不同的竞争状态,以使用不同的锁实现,这种切换就是锁的升级与降级。
没有竞争时默认使用的是偏向锁,通过CAS实现,当有另一线程试图争取被加偏向锁的对象时,JVM就升级为轻量级锁,如果获取成功则使用轻量级锁,否则进一步升级至重量级锁。
volatile的特点
-
保证对象在线程之间的可见性,当某一线程对对象做出修改时,其他线程能够通过此关键字 马上发现对象修改痕迹。
-
禁止指令重排,对象使用volatile修饰时,对此对象的操作JVM将不会进行重排。
-
不能保证原子性,当volatile变量改变时JVM会将值直接刷新到主内存中,但因为此操作并不是原子操作,所以在并发修改时需要加锁保证原子性。
Java中的指令重排
JVM在编译成class字节码文件时,会对代码进行优化,调整执行顺序,以此加快程序运行速度。
悲观锁与乐观锁区别
-
悲观锁:很悲观,认为当前对象会经常修改,所以无论读还是写时都会对对象加锁。
-
乐观锁:很乐观,认为当前对象不会经常修改,所以读并不会加锁,至于写的时候才会加锁。
什么是CAS
compare and swap,比较交换。其中包含三个值,分别为内存位置(V)、预期原值(A)、新值(B),如果内存位置中的值和原来的值是一样的,那么就将其修改为新值,如果不一样则以无限循环来自旋获取数据,每次循环如果内存位置中的值与预期的原值不同则继续自旋,直至相同。
什么是ThreadLocal
ThreadLocal是一个本地线程副本变量工具类,其中存储的值在各个线程中互不干扰,每个线程中都是一个单独的变量。
ThreadLocal本质上是在每一个Thread中维护了一个ThreadLocalMap,以ThreadLocal对象作为key,其值作为value,也就是一种以时间换空间的做法。ThreadLocal是一个弱引用,而其值一般为强引用,所以特殊情况下会造成内存泄漏的情况,即某一时刻将ThreadLocal对象置为null,也就是ThreadLocal没有强引用的了,同时此时触发发了GC,就会将当前ThreadLocal实例回收,而其值只能在当前线程销毁或者另一个ThreadLocal对象get或者set时刚好发现这个key为空才不会发生内存泄漏。所以建议使用完ThreadLocal对象调用remove方法清理一下值。
NIO、BIO、AIO区别
-
BIO:Java的传统IO模型,一个连接一个线程。其主要缺点为连接数与服务器线程成正比,有可能会造成不必要的线程开销,严重时还会导致内存溢出。
-
NIO:JDK1.4开始引入了新的IO模型,是同步非阻塞IO模型,多个请求一个线程。
-
AIO:JDK1.7发布了NIO2.0,这个是真正意义上的异步非阻塞的IO模型,多个有效请求一个线程,客户端的IO模型由OS完成后采取通知服务器去启动线程处理。
有哪些缓冲流
-
字节缓冲流:BufferedInputStream、BufferedOutputStream
-
字符缓冲流:BufferedReader、BufferedWriter
原理:创建流对象时会创建一个缓冲区数组,从而减少IO次数,提升读写效率。
序列化
Java序列化是一种处理对象流的机制,也就是将对象的内容流化,可以对流化后的对象进行读写操作,也可以将其在网络中传输,序列化就是为了解决对象流进行读写操作时所引发的问题。
实现序列化:将需要序列化的类实现Serializable接口,标识此类可以被序列化。Serializable接口为空接口,也就是没有需要实现的方法的接口。
OSI网络模型
-
物理层
-
数据链路层
-
网络层
-
传输层
-
会话层
-
表示层
-
应用层
TCP与UDP区别
-
TCP:面向连接,可靠,传输速度没有UDP快。HTTP、SMTP等协议底层为TCP协议。(适用于需要保证数据可靠性的传输)
-
UDP:无连接,不可靠,传输速度快。(适用于对数据可靠性相对不重要的传输,例如音视频流的传输等)
TCP三次握手与四次挥手
-
三次握手
-
客户端发起SYN请求:将本地socket状态设置为TCP_SYN_SENT,选择一个可用端口,发出SYN握手请求,并启动重传定时器。
-
服务端响应SYN:首先判断半连接队列是否满了,如果满了去tcp_syn_flood_action判断是否开启了tcp_syncookies内核参数,如果队列满,且未开启tcp_syncookies,则直接丢弃该请求。接着还要判断全连接队列,全连接队列满也会导致异常,如果全连接也满了且young_ack数量大于1,那么同样也是直接丢弃。
-
客户端相应SYNACK:客户端相应来自服务端的synack时清楚了connect时设置的重传定时器,把当前的socket状态设置为ESTABLISHED,开启保活计时器后发出第三次握手的ack确认
此处参考张彦飞《深入理解Linux网络》书中P159-P166
-
四次挥手
-
A数据传输完毕需要断开连接,A的应用进程向其TCP发出连接释放报文段(FIN = 1,序号seq = u),并停止再发送数据,主动关闭TCP连接,进入FIN-WAIT-1状态,等待B的确认。
-
B收到连接释放报文段后即发出确认报文段(ACK=1,确认号ack=u+1,序号seq=v),B进入CLOSE-WAIT关闭等待状态,此时的TCP处于半关闭状态,A到B的连接释放。而A收到B的确认后,进入FIN-WAIT-2状态,等待B发出的连接释放报文段。
-
当B数据传输完毕后,B发出连接释放报文段(FIN = 1,ACK = 1,序号seq = w,确认号ack=u+1),B进入LAST-ACK(最后确认)状态,等待A 的最后确认。
-
A收到B的连接释放报文段后,对此发出确认报文段(ACK = 1,seq=u+1,ack=w+1),A进入TIME-WAIT(时间等待)状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,A才进入CLOSE状态。
GET与POST区别
-
GET请求会被浏览器缓存,而POST不会。
-
GET请求只能将参数放到URL中,而POST可以放到请求体中。
-
GET请求不安全,参数直接暴露URL中,而POST可以避免这些风险。
-
GET请求参数由长度限制,POST没有。
本文使用 文章同步助手 同步
网友评论