synchronized锁升级是JVM自动完成的单向过程:无锁→偏向锁→轻量级锁→重量级锁。首次加锁触发偏向锁(CAS写入线程ID,标志位01+偏向位1);出现竞争时撤销偏向并升级为轻量级锁(标志位00,CAS争抢Lock Record);自旋失败或竞争加剧则升级重量级锁(标志位10,依赖Monitor和OS阻塞)。

Java 中 synchronized 的锁升级不是手动控制的,而是 JVM 在运行时根据对象锁的竞争情况,自动、单向地从低开销状态逐步“膨胀”到高开销状态的过程。整个路径是:**无锁 → 偏向锁 → 轻量级锁 → 重量级锁**,且不可逆。
无锁到偏向锁:单线程首次加锁触发
对象刚创建时处于无锁状态,Mark Word 中锁标志位为 01,偏向位为 0。当第一个线程执行 synchronized 块时:
- JVM 检查对象头是否可偏向(未被锁定、未禁用偏向锁)
- 通过一次 CAS 将 Mark Word 改为偏向锁状态:锁标志位仍为 01,但偏向位设为 1,并写入当前线程 ID 和 epoch(偏向时间戳)
- 此后该线程再次进入同步块,只需比对线程 ID,匹配即直接执行,零同步开销
偏向锁到轻量级锁:出现第二个竞争线程时撤销并升级
当其他线程(如线程 B)尝试获取同一把锁时,发现 Mark Word 记录的是线程 A 的 ID,说明偏向被打破:
- JVM 触发“偏向撤销”,需等待全局安全点(safepoint)
- 若线程 A 已退出,对象头重置为无锁状态,线程 B 尝试获取轻量级锁
- 若线程 A 仍在运行,JVM 将其栈中相关记录拷贝,并将对象头 Mark Word 替换为指向线程 A 栈帧中 Lock Record 的指针,锁标志位变为 00
- 线程 B 同样在自己栈中新建 Lock Record,用 CAS 争抢对象头;失败则进入自旋(默认最多 10 次)
轻量级锁到重量级锁:自旋失败或竞争加剧时升级
轻量级锁适用于线程交替执行、竞争不激烈的场景。但以下任一情况会触发升级:
立即学习“Java免费学习笔记(深入)”;
- 线程自旋一定次数后仍未获得锁(JDK 默认 10 次,可通过
-XX:PreBlockSpin调整) - 检测到多个线程同时自旋等待(例如第三个线程加入竞争)
- JVM 判断当前竞争已不适合用户态自旋,需交由操作系统接管
- 升级后,对象头锁标志位变为 10,Mark Word 存储指向堆中 Monitor 对象 的指针,未抢到锁的线程进入阻塞队列,由 OS 调度唤醒
注意:偏向锁在新版本中已被弃用
由于偏向锁在多线程频繁切换、GC 安全点停顿等场景反而引入额外开销,JDK 10 开始标记为 @Deprecated,JDK 15+ 默认关闭(可通过 -XX:+UseBiasedLocking 显式启用,但不推荐)。实际生产环境中,轻量级锁和重量级锁仍是主流路径。


















