偏向锁和轻量级锁的升级是JVM根据竞争动态触发的防御等级提升:偏向锁在无竞争时零开销,有竞争时撤销并升级为轻量级锁;后者通过自旋避免挂起,自旋失败则升级为重量级锁。

偏向锁和轻量级锁的升级,本质是 JVM 在检测到竞争加剧时,为保障正确性而主动提升锁的“防御等级”,不是线程主动申请,而是由运行时环境根据实际争抢行为动态触发。
偏向锁:单线程场景下的零开销优化
对象刚创建时若处于可偏向状态(JDK 8 默认开启,但延迟约 4 秒激活),首个进入 synchronized 块的线程会通过一次 CAS 将自身 ID 写入对象头 Mark Word,锁标志位保持 01、偏向位设为 1。此后该线程再次进入,只需比对线程 ID,完全跳过同步操作——没有 CAS,没有自旋,也没有上下文切换。
关键点:
- 偏向锁不释放,只在有竞争时才被撤销;
- 撤销必须等待全局安全点(safepoint),暂停所有用户线程;
- JDK 15+ 默认禁用,JDK 10 起已标记为 deprecated,生产环境需评估是否保留。
从偏向锁到轻量级锁:竞争出现时的平滑过渡
当第二个线程尝试获取已被偏向的锁,JVM 就触发升级。它先撤销原偏向状态(清空线程 ID、关闭偏向位),把对象重置为“无锁但锁标志仍为 01”的状态;接着立即为当前持有锁的线程分配轻量级锁:
立即学习“Java免费学习笔记(深入)”;
- 在持有锁线程的栈帧中新建一个 Lock Record;
- 把当前 Mark Word(此时已是无锁状态)复制进该记录作为 Displaced Mark Word;
- 再用 CAS 将对象头替换成指向这个 Lock Record 的指针,锁标志位改为 00。
此时锁仍由原线程持有,只是形态变了——后续其他线程来抢,就得走轻量级锁的竞争流程。
轻量级锁的竞争与自旋逻辑
新线程尝试获取轻量级锁时,也会在自己栈中建 Lock Record,并把对象头当前值(即指向原线程锁记录的指针)存进去;然后用 CAS 尝试将对象头替换为自己锁记录的地址:
- CAS 成功 → 拿到锁,直接执行;
- CAS 失败 → 进入自旋(默认最多 10 次),反复尝试,不挂起线程;
- 自旋期间线程仍在用户态运行,避免陷入内核态,节省调度开销。
只要竞争不激烈、临界区执行快,自旋往往能等来锁释放,无需进一步升级。
升级不是“加锁”,而是“换实现”
整个过程没有显式调用或配置动作,全由 JVM 自动完成:
- 偏向锁 → 轻量级锁:因“其他线程来抢”,非持有者触发;
- 轻量级锁 → 重量级锁:因“自旋失败”或“多个线程同时自旋”,JVM 判定竞争已超出轻量级处理能力;
- 所有升级都不可逆,且仅发生在锁被争抢的那一刻,不是定时或按次数累计。
理解这一点,就能明白为什么压测时突然出现大量 BLOCKED 线程——那往往是轻量级锁自旋耗尽后集体膨胀为重量级锁的结果。


















