偏向锁从JDK 15起默认禁用,需显式添加-XX:+UseBiasedLocking启用;JDK 21已彻底移除。其生效依赖JVM版本、运行时参数(如启动延迟、自旋阈值)、硬件架构及对象生命周期,不同环境锁升级路径差异显著。

synchronized 锁升级不是纯逻辑判断,它高度依赖 JVM 实现、运行时参数配置和底层硬件环境,不同环境下的行为可能完全不同。
JVM 版本与默认开关直接影响锁路径
从 JDK 15 开始,偏向锁被默认禁用(-XX:+UseBiasedLocking 默认为 false);JDK 17 LTS 中仍保留但需显式开启。若未启用,对象一创建就跳过偏向锁阶段,直接走轻量级锁逻辑。而 JDK 8–10 环境下,偏向锁默认开启,且会在类加载后 4 秒延迟激活(可通过 -XX:BiasedLockingStartupDelay=0 关闭延迟)。版本差异会导致同一段代码在不同 JDK 上锁状态跃迁次数、时机甚至是否触发自旋都不同。
运行时参数决定锁行为边界
锁升级不是自动“智能决策”,而是由一系列可调参数控制的硬规则:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- -XX:BiasedLockingStartupDelay 控制偏向锁何时可用
- -XX:CompileThreshold 和 JIT 编译时机影响锁优化生效时间(未被 JIT 编译的方法不参与锁消除或粗化)
- -XX:PretenureSizeThreshold 或 GC 策略间接影响对象分配位置,而偏向锁仅对普通堆对象有效,TLAB 分配的对象初始也支持偏向,但 Eden 区快速晋升可能绕过偏向阶段
- -XX:SpinLimit(旧版)或自适应自旋策略(JDK 6+)决定轻量级锁自旋多少次才升级——该阈值受 CPU 核数、当前系统负载动态调整
CPU 架构与操作系统决定重量级锁开销
重量级锁依赖 OS 的互斥量(mutex),其性能直接受内核调度能力制约:
立即学习“Java免费学习笔记(深入)”;
- 在 Linux 上,synchronized 最终映射为 futex,用户态竞争失败后才陷入内核;而在 Windows 上对应 CriticalSection,机制不同但同样涉及态切换
- 单核 CPU 环境下,自旋几乎无效,轻量级锁更容易快速升级为重量级锁;多核环境下,适度自旋反而减少上下文切换,提升吞吐
- 容器环境(如 Docker)若限制 CPU quota 或 shares,可能导致线程调度延迟,使自旋等待超时,提前触发锁膨胀
对象生命周期与内存布局是升级前提
锁升级只发生在堆中常规分配的对象上:
- 栈上分配(逃逸分析成功)的对象不会参与锁升级,JVM 可能直接锁消除
- 大对象(超过 TLAB 大小)直接进入老年代,但偏向锁仍可生效;不过 CMS 或 ZGC 等 GC 器在并发标记阶段会批量撤销偏向锁,强制升级
- 对象头结构随 JVM 位宽和压缩指针开关变化:64 位 JVM 启用压缩指针时 Mark Word 为 64bit,线程 ID 占 54 位;32 位 JVM 则线程 ID 仅 23 位,容易因 ID 冲突提前撤销偏向锁

















