提纲:
🔥Sychronized 锁
原理
偏向锁
轻量级锁
重量级锁
🎈面试八股真题
1、说一下线程之间是如何通信的
2、CAS的原理是什么
3、CAS有什么缺点
4、引用类型有哪些?有什么区别?
一、Sychronized 锁
1. 原理
-
使用对象中的 monitor 管程实现加锁与解锁,JDK 中为了提高效率,将 Sychronized 锁根据是否发生并发争抢分为了偏向锁,轻量级锁,和重量级锁
2.偏向锁
-
1、通过修改对象头中的偏向锁标记为 1,并且将 HashCode 与 Age 部分替换为当前持有偏向锁的线程 ID
-
2、在线程获取偏向锁时,若 ThreadID 就是自己,就直接获取,没有额外开销,若 ThreadID不是指向自己,且没有发生争抢,就进行冲偏向
-
3、偏向锁重偏向发生一定次数,JVM 就会认为不该添加偏向锁,并为当前类的所有对象以及以后创建的对象都撤销偏向锁
3.轻量级锁
-
1、轻量级锁的原理是通过在线程栈中创建一个锁记录,在锁记录中保存锁对象头的信息,并将标记加锁情况的两位改为 10 表示轻量级锁,将对象头中其他部分改为锁记录的指针
-
2、在线程获取轻量级锁时,根据加锁情况的两位发现加了轻量级锁,若锁记录指向自己的线程栈,则在线程栈中再添加一条空的锁记录,用来表示锁重入,在释放时按后进先出的顺序弹出锁记录
-
3、若当前持有轻量级锁的线程不是自己,则发生了争抢,但轻量级锁不会立刻升级为重量级锁,而是线程在原地 while 自旋一定次数后,若还没获取到锁,就升级为重量级锁,自旋的次数是 JVM动态决定的,根据自旋的成功与否对其进行加减
4.重量级锁
-
1、通过 monitor 管程来进行加锁,monitor 中主要有 Owner 指向当前持有锁的线程,EntryList 表示等待队列,以链表的方式存储被 Sychronized 阻塞的线程,WaitSet 表示调用了 wait 方法进行等待的线程队列
-
2、在线程获取锁时,将对象头中的锁信息改为 00 表示重量级锁,并调用 monitorEnter 指令获取对象的 monitor 管程,将对象头中其他部分替换为 monitor 的指针,将 monitor 的 Owner 指向当前线程
-
3、线程获取锁时,若对象已经加了重量级锁,就通过对象头的 monitor 指针找到 monitor,并根据 Owner判断是否是锁重入,如果不是,就进入等待队列 EntryList 中,并进入 Blocking 状态
-
4、在线程释放锁时,会调用 monitorExit 指令进行释放,并唤醒 EntryList 中的