Java中synchronized底层依赖JVM的monitorenter和monitorexit指令,通过对象头Mark Word关联Monitor实现互斥,支持偏向锁、轻量级锁、重量级锁三级升级,且同步方法与代码块的字节码实现方式不同。

Java 中 synchronized 关键字的底层同步机制,依赖于 JVM 指令 monitorenter 和 monitorexit,而非 Java 语言层的语法糖。它本质上是通过对象头中的 Monitor(监视器)来实现互斥访问。
monitorenter 指令触发 Monitor 获取
当线程执行到 synchronized 代码块入口时,JVM 会插入 monitorenter 指令。该指令尝试获取目标对象(或类的 Class 对象)关联的 Monitor:
- 若 Monitor 未被占用,当前线程直接持有,并将锁计数器置为 1;
- 若 Monitor 已被同一线程持有(可重入),则计数器 +1;
- 若 Monitor 被其他线程持有,当前线程进入阻塞状态,等待被唤醒(进入 EntryList 或 WaitSet)。
Monitor 的结构与对象头关联
每个 Java 对象在堆中都有一个对象头(Object Header),其中包含 Mark Word。Mark Word 在锁未膨胀时存储哈希码、GC 分代年龄等信息;一旦发生竞争,可能被替换为指向 Monitor 的指针。
Monitor 本身是 JVM 内部的 C++ 对象(ObjectMonitor),包含:
立即学习“Java免费学习笔记(深入)”;
- _owner:指向持有锁的线程;
- _EntryList:等待获取锁的线程队列;
-
_WaitSet:调用
wait()后挂起的线程队列; - _recursions:重入次数;
- _count:锁计数器(用于区分偏向锁、轻量级锁、重量级锁状态)。
synchronized 方法的字节码表现
对于 synchronized 实例方法,JVM 不显式插入 monitorenter/monitorexit,而是通过方法访问标志 ACC_SYNCHRONIZED 标识。执行该方法前,JVM 自动完成 Monitor 获取;方法退出(正常或异常)时自动释放。
而同步代码块(如 synchronized(obj) { ... })则明确生成两条指令:
- 在代码块入口插入
monitorenter; - 在所有可能的出口(包括异常出口)插入
monitorexit,确保锁一定被释放。
锁升级过程影响 monitorenter 行为
现代 HotSpot JVM 实现了锁优化(偏向锁 → 轻量级锁 → 重量级锁)。monitorenter 的具体行为取决于当前锁状态:
- 偏向锁阶段:检查 Mark Word 中线程 ID 是否匹配,无需 CAS;
- 轻量级锁阶段:用 CAS 将 Mark Word 替换为指向栈中 Lock Record 的指针;
- 重量级锁阶段:真正将线程挂起,交由操作系统 Mutex 等机制调度。
这些优化对开发者透明,但 monitorenter 始终是统一入口点,JVM 根据对象状态动态选择实现路径。


















