synchronized底层依赖每个Java对象关联的Monitor(监视器锁),本质是JVM通过对象头Mark Word管理、基于操作系统Mutex Lock实现的重量级同步原语,核心包含Owner、Entry Set和Wait Set三部分。

synchronized 底层靠的是每个 Java 对象关联的监视器锁(Monitor),它不是 Java 语言层面的抽象,而是 JVM 实现的同步原语,本质依赖操作系统提供的互斥锁(Mutex Lock)。
Monitor 的核心组成
每个 Monitor 包含三个关键部分:
- Owner:当前持有锁的线程。只有 Owner 能执行 synchronized 块内的代码;其他线程必须等待。
- Entry Set:等待获取锁的线程队列。当 Owner 释放锁时,JVM 会从 Entry Set 中随机唤醒一个线程(非公平策略),让它尝试竞争锁。
-
Wait Set:调用
obj.wait()的线程所处的等待队列。线程进入 Wait Set 前必须已持有该对象的 Monitor 锁;进入后自动释放锁,并暂停执行;被notify()或notifyAll()唤醒后,不会立即执行,而是重新回到 Entry Set 等待再次获取锁。
加锁与释放锁的过程
当线程执行到 synchronized(obj) 时:
- 先检查 obj 关联的 Monitor 是否空闲(Owner 为 null);是则直接获取锁,Owner 设为自己,继续执行。
- 否则进入 obj 的 Entry Set 阻塞等待,直到被唤醒并成功竞争到锁。
- 退出 synchronized 块时,Owner 清空,同时触发一次“唤醒”动作——从 Entry Set 中选一个线程唤醒(不一定按先进先出),也可能唤醒 Wait Set 中的线程(如果刚执行了 notify)。
锁对象到底是谁?
锁对象取决于 synchronized 的使用方式:
立即学习“Java免费学习笔记(深入)”;
- 修饰实例方法:
synchronized void m() { }→ 锁的是this(当前对象实例)。 - 修饰静态方法:
static synchronized void m() { }→ 锁的是MyClass.class(该类的 Class 对象)。 - 修饰同步代码块:
synchronized(obj) { }→ 锁的是括号中指定的任意非 null 对象。
注意:锁的是对象本身,不是代码段。两个线程操作不同对象的 synchronized 实例方法,完全不互斥;而操作同一个类的 static synchronized 方法,哪怕对象不同,也会争同一把 Class 锁。
Monitor 如何与对象绑定?
JVM 在对象头(Mark Word)中存储锁状态信息。对象创建初期处于“无锁”状态;随着竞争升级,可能依次变为偏向锁、轻量级锁、重量级锁。当升级为重量级锁时,JVM 就会在对象头中记录指向对应 Monitor 的指针,真正启用基于操作系统的互斥机制。
也就是说,Monitor 并非对象创建时就分配的实体,而是在需要重量级同步时才懒加载并关联的系统资源。


















