重量级锁是JVM在轻量级锁自旋失败且竞争加剧时自动触发的锁膨胀结果;其标志是Mark Word从指向栈中锁记录变为指向ObjectMonitor,由_monitor统一调度线程入队阻塞。

重量级锁在多线程竞争时不是“主动设置”的,而是JVM自动触发的锁膨胀(Lock Inflation)结果。它发生在轻量级锁已无法应对当前竞争强度的情况下,核心是“自旋失败 + 竞争加剧”双重信号共同推动。
轻量级锁自旋失败是直接导火索
当多个线程尝试获取同一把轻量级锁时,抢不到锁的线程不会立刻阻塞,而是进入自旋循环——反复用CAS操作尝试抢占锁记录。JVM默认有自旋次数阈值(如10次,具体由-XX:PreBlockSpin控制,或采用适应性自旋)。一旦某线程自旋超限仍未成功:
- 该线程放弃CPU时间片,准备进入阻塞状态
- JVM判定“仅靠自旋已无法高效协调竞争”,启动锁膨胀流程
- 对象头Mark Word从“指向栈中锁记录(00)”更新为“指向ObjectMonitor指针(10)”
更多线程参与竞争会加速膨胀
即使单次自旋未达阈值,若短时间内有第三个、第四个线程加入争抢,JVM会感知到竞争规模扩大。此时:
- 轻量级锁的CAS抢锁成功率显著下降
- 继续自旋会造成更多CPU空转浪费
- JVM倾向于提前升级,避免性能雪崩——尤其当锁持有时间较长(如含I/O或sleep)时
膨胀后由ObjectMonitor统一调度所有线程
升级为重量级锁后,对象关联的ObjectMonitor结构开始接管:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
立即学习“Java免费学习笔记(深入)”;
- _owner字段记录当前持锁线程
- _cxq(竞争队列)接收新到来的竞争线程(插入队头)
- _EntryList(等待队列)存放已排队、即将被唤醒的线程
- 后续线程调用monitorenter时,直接挂起并入队,不再自旋
典型触发代码场景
以下写法极易触发重量级锁:
Object lock = new Object();
new Thread(() -> {
synchronized(lock) {
try { Thread.sleep(500); } catch (InterruptedException e) {}
}
}).start();
new Thread(() -> {
synchronized(lock) { // 此处大概率触发膨胀
System.out.println("entered");
}
}).start();
原因:第一个线程长时间持锁 → 第二个线程自旋无效 → JVM立即升级为重量级锁,第二个线程被阻塞挂起而非空转。

















