重量级锁膨胀是synchronized在高竞争下的最终保障,通过将锁控制权移交内核态、依赖Mutex实现阻塞唤醒;触发条件包括自旋失败(默认10次)、持有线程被挂起或JVM主动跳过自旋;膨胀时分配ObjectMonitor、更新Mark Word指向它、转移锁所有权;运行时线程阻塞/唤醒由Monitor控制,开销大但避免CPU空转;膨胀不可逆,且JDK15起偏向锁已废弃。

重量级锁膨胀是 synchronized 在高竞争场景下的最终保障机制,本质是把锁的控制权从用户态移交到操作系统内核态,依赖真正的互斥量(Mutex)来实现线程阻塞与唤醒。
什么时候会触发重量级锁膨胀
轻量级锁在自旋尝试获取失败后升级为重量级锁。典型条件包括:
- 多个线程同时竞争同一把锁,且自旋一定次数(默认10次,由 -XX:PreBlockSpin 控制)后仍未成功
- 持有轻量级锁的线程被调度挂起(如发生长时间 GC、sleep 或 I/O),导致其他线程无法通过自旋等待
- JVM 检测到该对象锁频繁发生竞争,主动跳过自旋,直接走重量级路径(例如开启 -XX:+UseHeavyMonitors)
膨胀过程的三步关键操作
当 JVM 决定 inflate(膨胀)时,会执行以下底层动作:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 分配 ObjectMonitor 对象:在 C++ 堆中创建一个 Monitor 实例,包含 _owner(当前持有者)、_EntryList(等待队列)、_WaitSet(wait 队列)等字段
- 更新对象头 Mark Word:用原子操作(CAS 或 store)将对象头的锁标志位设为 11,并把内容替换成指向该 Monitor 的指针
- 转移锁所有权:若原轻量级锁持有线程仍在临界区内,_owner 就设为它;若已退出,则 _owner 置空,新线程可立即 acquire
重量级锁运行时的表现
一旦进入重量级状态,后续所有线程的行为就完全由 Monitor 控制:
立即学习“Java免费学习笔记(深入)”;
- 未获得锁的线程调用 monitorenter 时,会被放入 _EntryList 并调用操作系统 pthread_mutex_lock 进入阻塞态(BLOCKED)
- 持有锁的线程退出同步块后,JVM 调用 ObjectMonitor::exit(),清空 _owner,并从 _EntryList 中随机唤醒一个线程(非公平策略)
- 线程阻塞/唤醒涉及用户态到内核态切换,开销显著高于轻量级锁的自旋,但能避免 CPU 空转浪费
注意:膨胀不可逆,且现代 JDK 已弱化偏向锁
锁一旦升级为重量级,就不会再降级回轻量级或偏向锁。另外,从 JDK 15 开始偏向锁已被标记为废弃,JDK 18 默认禁用——这意味着在新版本中,无竞争时直接走轻量级锁路径,竞争加剧后更快进入重量级锁阶段。

















