外观
一句话答案
锁升级路径:无锁→偏向锁(Mark Word 记录线程 ID)→轻量级锁(CAS 竞争)→重量级锁(Monitor 阻塞),不可降级。
核心要点
锁升级过程:
无锁 → 偏向锁 → 轻量级锁 → 重量级锁
(单线程) (短时竞争) (激烈竞争)| 锁状态 | 适用场景 | 实现方式 | 开销 |
|---|---|---|---|
| 偏向锁 | 只有一个线程访问 | Mark Word 记录线程 ID,后续无需 CAS | 几乎无 |
| 轻量级锁 | 多线程交替执行 | CAS 替换 Mark Word 为栈中 Lock Record | CAS 开销 |
| 重量级锁 | 多线程同时竞争 | Monitor(mutex),未获锁线程阻塞 | 线程阻塞/唤醒 |
升级触发条件:
- 偏向→轻量级:第二个线程尝试获取锁时
- 轻量级→重量级:CAS 自旋超过阈值(默认10次/自适应)
关键细节:
- JDK15 默认关闭偏向锁(
-XX:-UseBiasedLocking) - 锁只能升级不能降级(GC 时特殊情况除外)
- 偏向锁撤销需要等安全点(STW)
追问与易错
追问方向:
- 偏向锁撤销的代价?
- JDK15 为什么关闭偏向锁?
- Mark Word 在不同锁状态存什么?
易错点:
- ❌ 锁能降级——正常情况只升不降
- ❌ 偏向锁就是不加锁——有 CAS 设置线程 ID 的开销
💡 记忆锚点
锁升级像排队看病:平时只有你一个人就直接进诊室(偏向锁,记你的 ID),来了第二个人就在门口轮流转圈等(轻量级锁,CAS 自旋),人太多转不动了就老实坐候诊区排队叫号(重量级锁,Monitor 阻塞)。只升不降,JDK15 直接取消了"一个人就不排队"的偏向优惠。