偏向锁通过首次cas登记线程id、后续仅比对id实现无竞争时零开销同步;适用于单线程高频访问场景,但多线程竞争会触发stw撤销,jdk15起默认禁用。

偏向锁在无竞争时提升性能,核心是把“每次进同步块都要检查+争抢”变成“第一次登记、后续直接放行”。它不靠原子指令抢锁,而是靠身份比对做快速判定。
一次登记,后续免检
当某个线程第一次进入 synchronized 块时,JVM 会用一次 CAS 把该线程 ID 写入对象头的 Mark Word,并标记为偏向状态。之后这个线程再进来,只需读取 Mark Word、比对线程 ID 是否匹配——成功就直接执行,完全跳过 CAS、不触发同步原语、也不涉及操作系统调度。
- 省掉每次加锁的 CAS 操作(含内存屏障和缓存一致性开销)
- 避免轻量级锁所需的栈帧 Lock Record 分配与维护
- 整个过程只是一次普通内存读取,接近无锁开销
对象头结构专为免检设计
HotSpot 在偏向锁状态下重定义 Mark Word 布局:54 位存线程 ID(64 位 JVM),2 位 epoch,4 位分代年龄,锁状态位仍为 01。这种紧凑布局让 JVM 仅靠一次内存读就能完成全部校验,无需写操作或总线锁定。
- 读取即验证,无副作用
- 不修改内存,不引发缓存行失效
- 适合高频、短临界区的单线程调用场景
适用场景明确,收益才真实
偏向锁不是通用加速器,只在以下情况带来可观收益:
- 对象长期被同一个线程反复访问(如 Spring 初始化 Bean、ThreadLocal 初始化逻辑)
- 同步块执行极快,且基本没有跨线程调用(比如计数器递增、配置读取)
- 应用整体锁竞争率很低(如批处理、离线工具、日志收集器内部状态)
注意撤销成本,别让优化变负优化
一旦第二个线程尝试获取同一把锁,JVM 必须暂停持有线程(STW 小片段),将偏向状态撤销并升级为轻量级锁。这个过程比直接走轻量级锁路径更重。
- 频繁撤销会导致 STW 累积、GC 日志中出现 BiasedLockingRevocation 事件
- JDK 15 起默认禁用偏向锁,因现代应用多线程协作特征明显
- 可通过 -XX:+PrintBiasedLockingStatistics 观察撤销频率,决定是否关闭
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











