ObjectMonitor::enter是synchronized的底层核心方法,负责通过CAS抢占、自旋、_cxq/_EntryList队列管理及park/unpark机制实现锁竞争与线程调度。

Java 中 synchronized 的底层依赖于 JVM 内部的 ObjectMonitor,而 ObjectMonitor::enter 是其核心入口方法,负责竞争、排队、阻塞与唤醒等关键逻辑。它不直接暴露给 Java 层,而是由 JIT 编译器或解释器在遇到同步块/方法时调用。
ObjectMonitor::enter 的核心职责
该方法本质是「尝试获取对象监视器锁」,但不是简单地设个标志位,而是一套包含自旋、队列管理、线程挂起与唤醒的完整协作机制:
- 先尝试快速路径(fast-path):通过 CAS 原子操作抢占锁(
_owner == null且无竞争),成功则直接持有; - 失败后进入慢路径(slow-path),需处理竞争——将当前线程加入
_EntryList或自旋等待; - 若锁被占用且无法立即获取,线程可能被挂起(park),直到被持有锁的线程在退出时 unpark;
- 支持偏向锁、轻量级锁、重量级锁的升级流程,但
ObjectMonitor::enter主要介入重量级锁阶段(即已膨胀为 Monitor 对象)。
关键字段与状态流转
ObjectMonitor 内部维护多个关键字段,它们共同驱动锁行为:
-
_owner:指向当前持有锁的线程(非 null 表示已加锁); -
_WaitSet:等待在wait()上的线程链表(调用notify/notifyAll时从中迁移); -
_EntryList:等待获取锁的线程队列(竞争失败后 park 前入队); -
_cxq(Contention Queue):一个 LIFO 栈结构,用于快速暂存新来的竞争线程,后续会批量迁移至_EntryList; -
_recursions:重入计数(synchronized 可重入,该值记录嵌套深度)。
线程调用 enter 后,会按顺序检查:_owner 是否为空 → 是否为自己 → 是否可自旋 → 是否需入 _cxq → 是否需 park。
立即学习“Java免费学习笔记(深入)”;
典型执行流程(简化版)
以 HotSpot 源码(如 JDK 8u292)为参考,ObjectMonitor::enter 的主干逻辑大致如下:
- 线程首次尝试 CAS 设置
_owner,成功则设置_recursions = 1,返回; - 若
_owner == current_thread,说明是重入,仅递增_recursions; - 否则,尝试短暂自旋(尤其在多核且锁持有时间短时),避免立即挂起;
- 自旋失败后,线程被封装为
ObjectWaiter,push 到_cxq栈顶; - 随后调用
Thread::current()->park()挂起自身; - 当持有锁线程调用
exit时,会从_WaitSet或_cxq/_EntryList中挑选一个线程 unpark,使其重新参与锁竞争。
与 Java 层 synchronized 的映射关系
你写的每一处 synchronized(obj) { ... } 或 synchronized method(),在字节码中对应 monitorenter / monitorexit 指令。JVM 执行时:
-
monitorenter触发ObjectMonitor::enter(或更早的偏向锁/轻量锁逻辑); -
monitorexit触发ObjectMonitor::exit,负责释放锁、唤醒等待者; - 若发生异常未正常退出同步块,JVM 保证
monitorexit仍会被插入到异常出口,防止死锁。
注意:ObjectMonitor 是每个 Java 对象头中 mark word 指向的 C++ 对象,仅在锁膨胀后才真正分配和关联。


















