java 15 默认禁用偏向锁,因其依赖的“单线程长期持有对象”场景在多核、高并发、短生命周期对象为主的现代应用中已不适用,撤销开销大、内存占用高、stw影响严重,jdk 21 中彻底移除。

Java 15 默认禁用偏向锁,不是因为技术做错了,而是它原本服务的场景——单线程长期持有对象——在现代应用里越来越少见了。多核硬件普及、微服务高并发、短生命周期对象泛滥,让偏向锁从“优化”变成了“拖累”。
多核环境让“单线程持有”假设失效
偏向锁的设计前提很朴素:一个对象大概率只被同一个线程反复访问(比如初始化后的单例、线程局部缓存)。但如今 32 核、64 核服务器是常态,HTTP 请求被负载均衡分发到不同线程池,一个 Request 对象可能几十毫秒内就被多个线程轮番访问。此时“偏向”某个线程不仅没收益,反而成了竞争触发点。
- 只要第二个线程尝试加锁,就必须撤销偏向状态
- 撤销过程强制所有线程进入 safepoint,引发 STW 暂停
- 在高 QPS 场景下,这会直接拉高 P99 延迟,影响用户体验
短命对象让初始化成本得不偿失
Spring WebFlux、Quarkus、函数计算等框架大量创建存活时间极短的对象(如 RequestWrapper、ContextHolder),很多对象生命周期远小于 JVM 默认的偏向锁延迟(-XX:BiasedLockingStartupDelay=4000ms)。
- 对象刚被标记为“偏向”,还没来得及被第二次访问,就已被 GC 回收
- 每次创建对象都要判断是否可偏向、是否在延时期、是否已禁用——这些分支判断本身就有 CPU 流水线开销
- Mark Word 需额外预留空间存 threadID 和 epoch,64 位 JVM 下占 62 位,增加内存压力和 GC 负担
撤销路径比轻量级锁更重
偏向锁撤销不是一次 CAS 就能完成的事,它需要:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 遍历目标线程栈,查找并修复所有锁记录
- 多次 CAS 更新对象头 Mark Word
- 依赖全局 safepoint,无法并行执行
相比之下,轻量级锁失败只是单次 CAS 失败,无跨线程副作用;配合 UseAdaptiveSpinning,还能根据历史成功率动态调整自旋次数,避免空转浪费 CPU。
JVM 锁路径转向更稳健的演进方向
禁用偏向锁不等于放弃优化,而是把资源集中到更普适的路径上:
- 无锁 → 轻量级锁(CAS + 自旋)→ 重量级锁
- 轻量级锁升级为重量级锁前,可通过 ObjectMonitor 队列公平排队,不依赖全局 safepoint
- JDK 21 中偏向锁已被完全移除,代码和参数(如 -XX:+UseBiasedLocking)一并删除
这个转变背后,是 JVM 团队对真实生产环境的持续观察:在多数高并发 Web 场景中,轻量级锁 + 自旋已足够高效,且行为更可预测、更易调试。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










