synchronized 的本质是 JVM 对对象关联的 ObjectMonitor 进行加锁释放,其核心是“对象→对象头→Monitor指针→线程调度”;Monitor含_owner、_EntryList、_WaitSet三组件,支持锁升级与wait/notify协作。

Java 中 synchronized 的本质,就是对一个对象关联的 Monitor(监视器)进行加锁和释放。它不是语法糖的“假锁”,而是 JVM 内部真实存在的、由 C++ 实现的同步原语——ObjectMonitor。理解它,关键在于抓住“对象 → 对象头 → Monitor 指针 → 线程调度”这条主线。
Monitor 是每个 Java 对象的“内置同步控制器”
每个 Java 对象在创建时,JVM 都会为其隐式关联一个 Monitor(HotSpot 中是 ObjectMonitor 实例)。这个 Monitor 并不存储在 Java 堆的对象实例里,而是在 native 内存中独立分配;对象头(Mark Word)只是保存指向它的指针(重量级锁状态时)或其它锁信息(如偏向线程 ID、轻量级锁栈帧地址)。
Monitor 本身包含三个核心组件:
- _owner:当前持有锁的线程指针,只能有一个线程处于此状态;
- _EntryList:等待获取锁的线程队列(阻塞态,BLOCKED);
-
_WaitSet:调用
wait()后挂起的线程队列(等待态,WAITING)。
synchronized 执行时发生了什么
当线程执行到 synchronized(obj) 或同步方法时,JVM 触发 monitorenter 指令,实际做的是:
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 检查 obj 的 Mark Word 锁状态(无锁 / 偏向 / 轻量级 / 重量级);
- 若已升级为重量级锁,则尝试通过 CAS 将 _owner 设为当前线程;
- 若 _owner 为空,成功获取锁,计数器
_recursions置为 1; - 若 _owner 已是当前线程,说明重入,
_recursions++; - 若 _owner 是其他线程,则当前线程被加入 _EntryList,并挂起(park)。
退出同步块时,monitorexit 指令触发:_recursions--,归零后将 _owner 置空,并唤醒 _EntryList 中的一个线程(非公平策略)。
wait/notify 是 Monitor 的协作能力
wait()、notify()、notifyAll() 是 Object 的 native 方法,它们的操作对象就是该对象所关联的 Monitor:
- 调用
obj.wait()必须在 synchronized(obj) 块内,否则抛IllegalMonitorStateException; - 执行
wait()会立即释放 Monitor(_owner = null),并将当前线程放入 _WaitSet; -
notify()从 _WaitSet 挑一个线程移入 _EntryList;notifyAll()把全部移入; - 被唤醒的线程不会立刻执行,仍需重新竞争 _owner,与其他 EntryList 中的线程一样走完整获取流程。
锁升级是 Monitor 的性能优化机制
JDK 6 引入的锁升级策略,是为了避免一上来就用重量级 Monitor(涉及操作系统 mutex,开销大):
- 偏向锁:假设“无竞争”,Mark Word 记录首次获得锁的线程 ID,后续同线程进入直接成功;
- 轻量级锁:有轻微竞争时,线程在栈中创建 Lock Record,用 CAS 替换 Mark Word;
- 重量级锁:竞争激烈时,膨胀为真正依赖 Monitor 的锁,Mark Word 存 Monitor 地址。
升级不可逆,但撤销(如发生竞争)会触发锁膨胀。Monitor 只在重量级阶段才真正被激活并参与调度。

















