提纲:

🔥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 中的