面试官:你来谈一下 Synchronized- 轻量级锁
纸上得来终觉浅,绝知此事要躬行。
轻量级锁是什么?
是 jdk1.6 引入的一种锁优化方式。传统的重量级锁加锁需要使用操作系统的互斥量实现。消耗较大。引入轻量级锁在没有多线程竞争的前提下,通过 jvm 来实现加锁,减少传统的重量级锁使用操作系统互斥量产生的性能消耗。
轻量级锁提升性能的依据
对绝大部分的锁,在整个同步周期内都不存在竞争。即线程交替执行同步代码块(一个线程执行完,第二个线程才来访问执行)。 当存在两个线程同时访问一个同步代码块时,会从轻量级锁升级为重量级锁。
什么情况会升级为轻量级锁
1. 无锁
偏向标识 0 为不可偏向。
2. 已偏向
偏向标识为 1,但已偏向为某个线程(非当前线程),且无法进行重偏向。会进行锁升级,升级为轻量级锁。
轻量级锁加锁过程
1、判断锁标识,是否满足升级为轻量级锁条件。
锁标识为 001,表示无锁,并且不可偏向。
锁标识为 000 时,为轻量级锁,走轻量级锁重入逻辑
2、在栈中记录一条 Lock Reocrd,并将对象的 Mark Word 备份到 Lock Record.Displaced Mark Word 中(用于后续还原),将 owner 指向当前对象。

3、尝试通过 CAS 将锁对象的 Mark Word 更新为指向 Lock Record 的指针,并更新锁状态为 00

4、如果对象是轻量级锁标识,判断 Mark Word 是否指向当前线程的栈帧。如果是则为锁重入。将 Lock Record.Displaced Mark Word 设置为 null,如果不是,执行 5
5、线程获取轻量级锁失败,锁膨胀为重量级锁,对象头 Mark Word 改为指向重量级锁 monitor 的指针。获取锁失败的线程不会立即阻塞,先适应性自旋,尝试获取锁。到达临界值后,阻塞该线程,直到唤醒。
轻量级锁解锁过程
获取最新的一条 Lock Record,如果 Displaced Mark Word 为 null,如果是,则将 owner 设置为 null,如果不是执行 2
通过 CAS 把当前线程栈帧的 Lock Record 中的 Displaced Mark Word 替换到对象头的 Mark Word,如果替换成功,则轻量级锁解锁成功。如果替换失败,则说明 Mark Word 已经被替换为指向 Monitor,对象现在是重量级锁定状态,执行重量级锁释放。
作者:陈圆圆的编程笔记
链接:https://juejin.cn/post/7186106651764588604
来源:稀土掘金
评论