synchronized 的内部锁是 JVM 为每个对象隐式赋予的监视器,基于对象头 Mark Word 状态实现无锁→偏向锁→轻量级锁→重量级锁的自动升级,并通过 ObjectMonitor 管理线程竞争与等待,同时保障可见性与有序性。

synchronized 的内部锁本质上是每个 Java 对象自带的“监视器”(Monitor),它不依赖额外类库,而是由 JVM 在对象创建时就隐式赋予的。这个锁不是独立对象,而是绑定在对象头(Object Header)里的状态标记和关联结构。
锁与对象头紧密耦合
每个 Java 对象内存布局中都包含一个对象头,其中关键部分是 Mark Word。它会动态记录当前锁的状态:无锁、偏向锁、轻量级锁或重量级锁。JVM 通过原子操作(如 CAS)尝试修改 Mark Word 来完成加锁动作。比如线程第一次进入 synchronized 块时,若发现对象处于无锁状态,就用 CAS 将自己的线程 ID 写入 Mark Word,并把锁标志位设为“偏向锁”——这一步几乎不涉及操作系统调度,开销极小。
Monitor 是锁行为的实际执行者
当锁升级为轻量级或重量级后,JVM 会为该对象关联一个 ObjectMonitor 实例(由 C++ 实现,位于 HotSpot JVM 中)。它内部维护三个核心字段:
- _owner:指向当前持有锁的线程
- _EntryList:等待获取锁的线程队列(阻塞态)
- _WaitSet:调用 wait() 后挂起的线程队列(等待被 notify)
线程执行 monitorenter 指令时,实际是在尝试将自己设为 _owner;失败则进入 _EntryList 等待唤醒。释放锁时触发 monitorexit,并唤醒 _EntryList 中的一个线程竞争所有权。
立即学习“Java免费学习笔记(深入)”;
锁会根据竞争情况自动升级
JVM 不会一开始就用最重的锁机制。它按需演进:
- 无锁 → 偏向锁:单线程反复进入,只比对 Mark Word 中的线程 ID
- 偏向锁 → 轻量级锁:出现第二个线程竞争,转为在栈帧中新建 Lock Record 并用 CAS 尝试抢占
- 轻量级锁 → 重量级锁:自旋多次仍抢不到,线程挂起,Monitor 全面接管,依赖操作系统 Mutex
这个过程完全透明,开发者无需干预,但理解它有助于判断同步块是否真成了性能瓶颈。
锁释放与内存可见性自动保障
退出 synchronized 区域时,JVM 不仅清空 _owner、唤醒等待线程,还会插入内存屏障(Memory Barrier):
- 释放锁前:强制将线程本地工作内存中所有共享变量写回主内存
- 获取锁后:强制从主内存重新读取共享变量最新值
这就天然保证了可见性,不需要额外加 volatile。同时,synchronized 还禁止编译器和处理器对临界区内的指令做跨边界的重排序,从而维持有序性。


















