synchronized 同步块底层基于 JVM 的 monitor 机制,每个对象关联一个由对象头 Mark Word 动态维护的 monitor;通过 monitorenter/monitorexit 指令控制获取与释放,支持可重入、自动释放,并经锁升级(偏向锁→轻量级锁→重量级锁)优化性能。

synchronized 同步块的底层监控机制,核心是 JVM 对monitor(监视器)的管理,而非操作系统级锁或 Java 层面的显式对象。它依赖每个 Java 对象头中隐含的 monitor 结构,在字节码层面通过 monitorenter 和 monitorexit 指令触发。
monitor 是什么?
monitor 是 JVM 规范定义的一种同步原语,每个对象实例(包括 Class 对象)在创建时都关联一个 monitor。它不是 Java 对象,也不在堆内存中独立存在,而是由 JVM 在对象头(Object Header)的 Mark Word 中动态维护的状态结构。JVM 实现(如 HotSpot)通常将其映射为 C++ 的 ObjectMonitor 类实例,由 ObjectSynchronizer 模块统一管理。
进入和退出同步块的关键步骤
当线程执行 synchronized(obj) { ... } 时:
- JVM 在字节码中插入
monitorenter指令:线程尝试获取 obj 关联 monitor 的所有权;若 monitor 未被占用,线程直接持有并进入临界区;若已被其他线程持有,当前线程进入该 monitor 的 EntryList 阻塞等待 - 线程持有 monitor 后,monitor 的计数器(_count)加 1,表示重入次数(支持可重入)
- 执行完同步块后,JVM 插入
monitorexit指令:计数器减 1;若减为 0,则释放 monitor,并唤醒 EntryList 中的一个等待线程(具体策略取决于 JVM 参数,如 -XX:+UseSpinning 可启用自旋) - 即使发生异常,JVM 也保证
monitorexit被执行(编译器在异常表中插入对应清理逻辑),因此 synchronized 具有自动释放特性
monitor 的三种队列状态
HotSpot 中一个 monitor 包含三个关键等待队列:
立即学习“Java免费学习笔记(深入)”;
- EntryList:竞争 monitor 失败、等待获取锁的线程队列(阻塞态,需系统调用挂起)
-
WaitSet:调用
obj.wait()后挂起的线程队列(不参与锁竞争,仅响应 notify/notifyAll) - cxq(Contention Queue):快速竞争失败时暂存的线程链表,用于减少 CAS 竞争开销;后续可能被迁移至 EntryList
锁升级与优化(HotSpot 特有)
为减少 monitor 开销,HotSpot 引入锁膨胀机制,monitor 状态随竞争程度动态演进:
- 无竞争时:偏向锁(Biased Locking)—— mark word 记录偏向线程 ID,无需原子操作
- 轻度竞争:升级为轻量级锁(Lightweight Locking)——使用 CAS 尝试将 mark word 替换为指向栈中 Lock Record 的指针
- 重度竞争:膨胀为重量级锁(Heavyweight Locking)——真正构造 ObjectMonitor,线程进入 OS 级阻塞(park/unpark)
这些优化对 Java 代码透明,但可通过 JVM 参数控制,例如 -XX:-UseBiasedLocking 关闭偏向锁。


















