synchronized 底层依赖 JVM 的 Monitor 机制实现,Monitor 基于操作系统互斥锁构建,与每个 Java 对象关联,包含 _count、_owner、EntryList 和 WaitSet;其加锁/解锁通过 monitorenter/monitorexit 指令触发,支持重入与线程阻塞;wait/notify 也操作同一 Monitor 的 WaitSet,需在 synchronized 中调用。

synchronized 在 Java 底层依赖 JVM 提供的 Monitor(监视器) 机制来实现线程同步,而 Monitor 本身又基于操作系统提供的互斥锁(如 pthread_mutex 或 Windows Critical Section)构建。它不是 Java 语言层面的类或对象,而是 JVM 运行时的一个逻辑概念,与每个 Java 对象关联。
每个对象都有一个关联的 Monitor
JVM 为每个 Java 对象维护一个 Monitor 结构(存储在对象头中),包含:
- 一个 计数器(_count):记录当前持有锁的线程重入次数;
- 一个 指针(_owner):指向当前持有该 Monitor 的线程;
- 两个等待队列:EntryList(竞争锁失败后阻塞在此的线程)和 WaitSet(调用 wait() 后挂起的线程)。
synchronized 方法/代码块的执行流程
当线程执行 synchronized 代码时,JVM 会触发 Monitor 的加锁与解锁操作:
- 遇到
monitorenter字节码指令(对应 synchronized 块入口),尝试获取对象的 Monitor; - 若 Monitor 未被占用(_owner == null),当前线程直接成为 owner,并将 _count 设为 1;
- 若已被同一线程持有(可重入),则 _count++,不阻塞;
- 若被其他线程持有,当前线程进入 EntryList 并挂起(调用 OS 的 mutex lock 等待);
- 退出 synchronized 时执行
monitorexit,_count--,为 0 则释放 Monitor,唤醒 EntryList 中的一个线程。
wait/notify 也通过 Monitor 协作
Object 类的 wait()、notify()、notifyAll() 必须在 synchronized 块中调用,原因在于它们操作的是同一个 Monitor 的 WaitSet:
立即学习“Java免费学习笔记(深入)”;
-
wait():将当前线程从 Owner 状态移出,加入 WaitSet,并释放 Monitor(_count 归零、_owner 置空),然后挂起; -
notify():从 WaitSet 挑一个线程移入 EntryList,不立即唤醒,等当前线程退出 synchronized 后,它才有机会竞争 Monitor; - 这些操作都由 JVM 调用底层 OS 的条件变量(condition variable)配合互斥锁完成。
Monitor 不是 Java 对象,但可被观察
虽然 Monitor 是 JVM 内部结构,无法直接访问,但可通过工具间接验证其存在:
-
jstack输出中的 - locked 表示某线程持有某个对象的 Monitor; -
Unsafe.monitorEnter/monitorExit是 JVM 提供的底层接口(不推荐直接使用); - HotSpot 源码中
ObjectMonitor类(位于src/share/vm/runtime/objectMonitor.hpp)定义了 Monitor 的 C++ 实现。


















