偏向锁需同时满足JVM启用、延迟期过后、对象可偏向、首次单线程无竞争、安全点外执行及类未被批量撤销等条件才会生效,否则直接升级为轻量级锁。

偏向锁不是“自动开启”的,它需要同时满足多个前提条件才会被 JVM 启用。很多开发者以为只要用了 synchronized 就会走偏向路径,结果发现锁直接从无锁跳到轻量级锁——根本没进过偏向状态。问题往往出在这些隐含条件上。
对象必须处于“可偏向”初始状态
新创建的对象默认是无锁状态(Mark Word 中 biased_lock=0),但能否进入偏向锁,取决于 JVM 是否允许对该类开启偏向。JVM 在启动时默认启用偏向锁,但会在启动后延迟几秒才真正激活(通常 4 秒左右)。在这段“预热期”内,哪怕线程首次进入同步块,也不会设置偏向锁,而是直接走轻量级锁路径。
- 可通过
-XX:BiasedLockingStartupDelay=0关闭延迟,让偏向锁在启动即生效 - 也可用
-XX:-UseBiasedLocking彻底禁用偏向锁(常见于容器化或短生命周期应用) - 一旦禁用,所有对象都不会尝试进入偏向状态,锁升级直接从无锁 → 轻量级锁
首次加锁必须由单一线程完成,且无竞争发生
偏向锁只在“第一个线程首次获取锁”时尝试建立。这个过程要求:当前对象尚未被任何线程锁定,且 JVM 检测到该对象从未发生过锁争用(即对象头未被修改为其他锁状态)。
- 若对象刚被 GC 回收又重新分配,仍视为新对象,满足条件
- 但如果该对象此前已被其他线程加过锁(哪怕已释放),其 Mark Word 可能残留锁标记,导致偏向失败
- 多线程几乎同时调用同一同步块,哪怕只差纳秒级,也可能因 CAS 竞争失败而跳过偏向,直接升级为轻量级锁
线程需在安全点(safepoint)之外完成偏向操作
JVM 设置偏向锁本质是一次 CAS 写入对象头(将线程 ID 和偏向标志位写入 Mark Word)。这个操作不能在 GC 或其他 VM 暂停期间执行,否则会被推迟或取消。
立即学习“Java免费学习笔记(深入)”;
- 如果线程恰好在进入同步块时触发了 GC,JVM 可能跳过偏向,降级为轻量级锁
- 频繁触发 safepoint 的应用(如高频率 CMS GC)会显著降低偏向锁命中率
- 可通过
-XX:+PrintSafepointStatistics -XX:PrintSafepointStatisticsCount=1观察 safepoint 频次影响
类未被全局禁用偏向(bulk revocation)
JVM 会对频繁发生偏向撤销的类进行批量禁用:一旦某个类的实例多次因竞争导致偏向锁被撤销,JVM 会标记该类为“不可偏向”,后续新建实例直接跳过偏向阶段。
- 撤销阈值默认为 20 次(
-XX:BiasedLockingBulkRevokeThreshold=20) - 被批量禁用后,该类所有新对象都从无锁 → 轻量级锁,不再尝试偏向
- 可通过
-XX:+TraceBiasedLocking查看具体哪些类被 revoke


















