偏向锁升级为轻量级锁发生在第二个线程竞争时,需同时满足对象处于偏向锁状态且有其他线程尝试获取锁;JVM通过安全点暂停持有线程、清零偏向位、CAS更新为指向锁记录的指针来完成升级,过程不可逆且仅触发一次。

偏向锁升级为轻量级锁,发生在**有竞争出现的瞬间**,不是由持有线程主动释放,而是由竞争线程触发的被动撤销与升级过程。
升级发生的两个前提条件
必须同时满足以下两点,才会启动升级:
- 对象当前处于偏向锁状态(Mark Word 中偏向标志位为 1,锁标志位为 01)
- 有**第二个线程**尝试获取该锁,且发现锁已被其他线程偏向
具体升级步骤(JVM 内部执行)
以线程 A 持有偏向锁、线程 B 尝试竞争为例:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 线程 B 检查对象头,确认是偏向锁,并读取其中记录的线程 A ID
- JVM 判断线程 A 是否仍存活(是否还在运行中):
- 若线程 A 已退出同步块(比如已执行完 synchronized),对象头可能已恢复为无锁状态,此时线程 B 直接用 CAS 抢占,不升级
- 若线程 A 仍在运行(比如正持有锁执行中),则需安全地撤销偏向锁——这需要等待 JVM 的“安全点”(safepoint)
- 到达安全点后,JVM 暂停线程 A,将其栈帧中与该锁相关的 monitor record(如果有)准备好
- 将对象头锁标志位从 101 改为 00,偏向位清零,表示不再是偏向锁
- 用 CAS 将对象头更新为指向线程 A 栈帧中新建的 Lock Record 的指针
- 线程 A 继续执行,锁现在是轻量级锁;线程 B 开始自旋,尝试用 CAS 抢占同一 Lock Record
关键细节说明
这个过程有几个容易被忽略但影响实际行为的点:
立即学习“Java免费学习笔记(深入)”;
- 撤销必须等安全点:偏向锁撤销不是立即完成的,JVM 会延迟到最近的安全点执行,所以线程 B 可能短暂阻塞等待
- 升级只发生一次:一旦升级为轻量级锁,后续所有竞争都走轻量级或重量级逻辑,不会再回到偏向状态
- 偏向锁默认 4 秒后才启用:JVM 启动初期(默认前 4000ms)偏向锁被禁用,可通过 -XX:BiasedLockingStartupDelay=0 关闭延迟
- JDK 15+ 已移除偏向锁:在较新版本中该机制不存在,升级路径直接从无锁到轻量级锁

















