java中synchronized锁升级由jvm自动完成,路径为无锁→偏向锁→轻量级锁→重量级锁,单向不可逆,通过对象头mark word状态变化驱动,旨在平衡不同并发强度下的性能与正确性。

Java 中 synchronized 的锁升级不是程序员手动控制的,而是 JVM 在运行时根据线程竞争情况自动完成的优化过程。整个路径是单向不可逆的:无锁 → 偏向锁 → 轻量级锁 → 重量级锁,每一步升级都由对象头(Mark Word)的状态变化驱动,核心目标是在不同并发强度下平衡性能与正确性。
偏向锁:单线程场景下的零开销优化
当一个线程首次进入 synchronized 块时,JVM 检查对象是否处于无锁状态(Mark Word 锁标志位为 01),然后通过一次 CAS 将其设为偏向锁:记录当前线程 ID、设置偏向标志位(101)。此后该线程再次进入,只需比对 Mark Word 中的线程 ID,无需任何同步操作。
- 适用:getter/setter、单线程初始化等几乎无竞争的场景
- 撤销触发:其他线程尝试获取该锁;或到达全局安全点(safepoint)时批量撤销
- 注意:JDK 15+ 默认禁用,JDK 10 起已标记为 deprecated
轻量级锁:低竞争下的自旋争抢
一旦发生竞争(比如第二个线程来抢锁),JVM 撤销偏向状态,并在线程栈中创建 Lock Record,尝试用 CAS 将对象头替换为指向该记录的指针(锁标志位变为 00)。
- 成功:获得锁,直接执行
- 失败:进入自旋等待(默认最多 10 次),不挂起线程,避免内核态切换
- 升级条件:自旋失败、或检测到多个线程在等待,说明竞争加剧
重量级锁:高竞争下的操作系统级阻塞
当轻量级锁自旋耗尽,JVM 将锁膨胀为重量级锁:对象头指向堆中的 Monitor 对象(锁标志位 10),未获锁线程进入 Monitor 的 EntryList 并被操作系统挂起(BLOCKED 状态)。
- Monitor 底层调用 pthread_mutex(Linux)或 CriticalSection(Windows)
- 所有后续同步操作都走此路径,不再降级或回退
- 可通过
jstack观察线程状态为BLOCKED,对应持有 Monitor 的线程
无锁状态:初始起点,非“没有同步”
对象刚创建时,Mark Word 中锁标志位为 01,未记录任何线程信息,也不含锁结构。此时若线程进入 synchronized,就触发第一次升级。它不是“不需要同步”,而是“尚未被任何线程锁定”的待机状态。
整个升级过程完全由 JVM 自动决策,开发者无法干预。但可通过 -XX:+PrintBiasedLockingStatistics 等参数观察偏向锁使用情况,结合 jstack 和对象头分析工具(如 JOL)辅助诊断锁行为。不复杂但容易忽略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











