synchronized锁升级是jvm自动触发的单向过程:无锁→偏向锁→轻量级锁→重量级锁。偏向锁适用于单线程场景,通过cas记录线程id实现零成本重入;轻量级锁在竞争时采用自旋抢锁,失败则升级;重量级锁依赖objectmonitor,引发内核态切换与线程阻塞。

synchronized 锁升级不是人为控制的流程,而是 JVM 根据实际竞争情况自动触发的状态演进。整个过程围绕对象头中的 Mark Word 展开,状态只能单向升级:无锁 → 偏向锁 → 轻量级锁 → 重量级锁,不可降级。
偏向锁:单线程场景的零成本优化
对象首次被某个线程进入 synchronized 块时触发。JVM 检查 Mark Word 是否可偏向(锁标志位为 01,偏向标志位为 1),若满足,则通过一次 CAS 将当前线程 ID 写入,并标记为偏向该线程。
后续同一线程再次加锁,仅需比对 Mark Word 中的线程 ID,无需任何同步操作——几乎等同于没加锁。
关键细节:
- 偏向锁默认在 JVM 启动约 4 秒后才启用,可通过 -XX:-UseBiasedLocking 彻底禁用
- 撤销发生在第二个线程尝试获取锁时,需等待全局安全点(Stop-The-World 小暂停)
- 若原持有线程已退出同步块,对象可能重置为无锁;若仍在执行,则直接升级为轻量级锁
轻量级锁:低竞争下的自旋抢夺
偏向锁被撤销后,或对象本就不支持偏向(如禁用了偏向锁),第一个竞争线程会尝试轻量级锁。此时线程在自己的栈帧中创建一个 Lock Record,将 Mark Word 的原始值(Displaced Mark Word)复制进去,再用 CAS 尝试把对象头替换为指向该记录的指针,锁标志位变为 00。
CAS 成功即获得锁;失败则说明已有其他线程抢先设置,当前线程进入自旋等待。
自旋不是无限的:
- JDK 默认自旋阈值为 10 次(可由 -XX:PreBlockSpin 调整)
- 现代 JVM 使用“适应性自旋”:根据前几次自旋是否成功动态调整次数
- 一旦自旋失败、或检测到多个线程同时争抢(如第三个线程加入),就放弃自旋,升级为重量级锁
重量级锁:高竞争下的内核级保障
当轻量级锁自旋耗尽仍无法获取锁,JVM 就将对象头的 Mark Word 替换为指向 ObjectMonitor 的指针,锁标志位设为 10。ObjectMonitor 是 C++ 实现的监视器对象,内部包含等待队列、阻塞队列和 owner 字段等。
此时未抢到锁的线程会被挂起,进入 BLOCKED 状态,等待操作系统调度唤醒。
代价明显:
- 用户态 → 内核态切换,上下文开销大
- 线程阻塞/唤醒涉及系统调用,延迟高
- 一旦升级为重量级锁,该对象后续所有加锁操作都走这条路径,不再尝试退回轻量级或偏向
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











