synchronized通过Monitor绑定的内存语义保证同步,进入时执行Load Barrier强制从主内存读最新值,退出时执行Store Barrier强制刷新修改到主内存,并提供原子性与有序性。

synchronized 在 Java 内存模型(JMM)中不是靠“加锁”这个动作本身保证同步,而是通过与监视器锁(Monitor)绑定的内存语义来实现线程间可见性、原子性和有序性。它的底层实现依赖 JVM 对 Monitor 的具体落地,核心在于进入/退出 monitor 时触发的内存屏障和主内存同步行为。
monitor 是什么:一个由 JVM 管理的同步原语
每个 Java 对象在创建时都关联一个 monitor(监视器),它本质上是一个操作系统级的互斥结构(如 Linux 的 mutex 或 Windows 的 CriticalSection),由 JVM 在对象头(Object Header)中维护状态(比如锁标志位、持有线程 ID、等待队列等)。synchronized(obj) 实际就是对 obj 关联的 monitor 执行 acquire/release 操作。
Monitor 不是 Java 语言层面的概念,而是 JVM 规范定义的抽象机制,HotSpot 中具体实现为 ObjectMonitor 结构体。
进入 synchronized 块时发生了什么
当线程执行 monitorenter(字节码指令,对应 synchronized 开始),JVM 会尝试获取目标对象的 monitor:
立即学习“Java免费学习笔记(深入)”;
- 如果 monitor 未被占用,当前线程成功获取,并把对象头中的锁标志设为“偏向锁/轻量级锁/重量级锁”对应状态;
- 如果已被其他线程持有,当前线程进入阻塞或自旋等待(取决于锁升级策略);
- 关键内存行为:成功获取 monitor 后,线程会清空本地内存(工作内存)中该对象字段的缓存值,后续读取必须从主内存重新加载——这保证了“看到最新写入”;
- JVM 在 monitorenter 后插入LoadLoad + LoadStore 屏障,防止指令重排序导致读操作提前到锁获取之前。
退出 synchronized 块时的关键语义
执行 monitorexit(对应 synchronized 结束)时:
- 线程释放 monitor,唤醒等待队列中的一个线程(若有);
- 所有在临界区中修改过的共享变量,都会被强制刷新回主内存——这是 JMM 规定的“解锁操作具有 store-store 屏障 + store-load 屏障”的效果;
- 其他后续获取同一 monitor 的线程,就能通过再次加载看到这些更新,从而满足happens-before 关系(unlock happens-before lock)。
与 volatile 的区别:不只是“读写屏障”
volatile 只提供单次读/写的可见性与禁止重排序;而 synchronized 围绕 monitor 构建了一整套原子块 + 全局内存同步 + 线程调度协同机制:
- 它天然具备原子性(整个临界区不可分割);
- 它隐式完成“读-改-写”全过程的内存同步(比如 i++ 在 synchronized 块内是线程安全的);
- 它还提供线程阻塞/唤醒能力,可用于协调执行顺序(如 wait/notify)。
不复杂但容易忽略:synchronized 的威力不在“锁住代码”,而在它让 JVM 在关键节点插入内存屏障、强制主内存同步,并通过 monitor 状态联动线程调度与缓存一致性。


















