偏向锁撤销后先进入轻量级锁,而非直接升级为重量级锁;其路径为:撤销后恢复无锁状态或替换为指向lock record的指针(标志位00),仅当自旋失败(如超10次)才升级为重量级锁(标志位10)。

偏向锁撤销后,**不是直接变成重量级锁,而是先进入轻量级锁**——这是 JVM 锁升级机制的关键逻辑,也是很多开发者容易误解的地方。
偏向锁撤销时的典型路径
当第二个线程尝试获取一个已偏向某线程的对象锁时,JVM 会触发偏向锁撤销流程。这个过程不是“跳过中间态”,而是有明确的后续状态选择:
- 如果原偏向线程已不活跃(比如已退出同步块、栈帧中无相关锁记录),JVM 会将对象头恢复为无锁状态(标志位 01),新线程可重新竞争,大概率走轻量级锁路径;
- 如果原偏向线程仍在运行且持有该锁(例如正在执行同步代码块),JVM 会在安全点暂停它,把对象头中的偏向信息替换为指向当前线程栈中Lock Record 的指针,此时锁状态变为轻量级锁(标志位 00);
- 只有在轻量级锁阶段发生自旋失败(比如竞争激烈、自旋耗时超阈值),才会进一步升级为重量级锁(标志位 10)。
为什么不会跳过轻量级锁?
轻量级锁的设计目标就是在存在竞争但尚不严重时,用用户态自旋替代内核态阻塞,避免线程挂起/唤醒开销。跳过它直接上重量级锁,就等于放弃这一层关键优化:
- 自旋本身成本低,适合短时间等待;
- 重量级锁涉及操作系统互斥量(ObjectMonitor)、线程阻塞队列(EntryList)、上下文切换等,开销大得多;
- JVM 默认会先尝试自旋(默认10次,可通过 -XX:PreBlockSpin 调整),失败后才升级。
实际中偏向锁常被绕过
虽然理论路径是「偏向 → 轻量级 → 重量级」,但现实中很多场景会跳过偏向锁阶段:
- JDK 15+ 默认禁用偏向锁(-XX:-UseBiasedLocking),新对象直接从无锁进入轻量级锁;
- 应用启动初期若已有多个线程竞争同一类对象,JVM 可能批量禁用该类的偏向锁;
- 频繁撤销偏向锁的对象,会被 JVM 标记为“不适合偏向”,后续实例直接走轻量级锁路径。
小结:撤销 ≠ 升级到最重
偏向锁撤销是一个“清理旧状态”的动作,它本身不决定新锁级别;真正决定下一步的是当前竞争强度和线程活动状态。绝大多数情况下,撤销后对象会进入轻量级锁状态,再根据自旋结果决定是否继续升级。理解这一点,才能准确把握 synchronized 在不同并发压力下的行为差异。










