synchronized退出同步块时,JVM强制将块内实际修改过的共享变量刷新回主内存,这是JMM规定的必须行为;通过StoreStore+StoreLoad屏障禁止重排序,与锁释放共同构成happens-before关系,确保其他线程可见。

Java 变量在 synchronized 同步块中退出时刷入主内存,靠的是 JVM 自动插入的 StoreStore + StoreLoad 内存屏障,不是手动控制,也不依赖线程调度,而是 JMM 规定的强制行为。
同步块退出时的刷新是精准且确定的
只刷那些在块内被实际修改过的共享变量,不是全部字段都写回:
- 局部变量、未被其他线程访问的私有字段,不会触发刷新
- 即使某个 volatile 或普通字段在块内被多次读取,只要没被赋新值,就不会写回主内存
- JVM 通过静态分析和运行时跟踪识别“真正被写入”的变量,避免无谓带宽消耗
内存屏障如何保障刷新不被乱序
在 monitorexit 指令前,JVM 插入 StoreStore 屏障,确保两件事严格有序:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 所有同步块内已完成的写操作(如 x = 1、list.add(item))必须先完成并落主存
- 这些写不能被 JIT 编译器或 CPU 重排到锁释放之后
- StoreLoad 屏障进一步防止后续非同步代码的读/写提前穿插进来
刷新动作与 happens-before 关系直接绑定
这个写回不是孤立动作,它和锁释放共同构成 JMM 中的关键同步契约:
立即学习“Java免费学习笔记(深入)”;
- 线程 A 退出 synchronized 块 → 修改刷入主内存 + 锁释放
- 线程 B 进入同一把锁的同步块 → 强制清空本地缓存副本 → 从主内存重新加载变量
- A 的写与 B 的读之间自动建立 happens-before,B 一定看到 A 的最新值
和 volatile 刷内存的区别在哪
两者都靠内存屏障,但作用粒度和语义不同:
- volatile 写:只刷该变量本身,用 StoreStore + StoreLoad,配合 MESI 失效其他核心缓存行
- synchronized 退出:刷块内所有被改过的共享变量,范围更广,且天然带互斥和原子性保证
- volatile 不提供原子性,synchronized 刷内存的同时也保证临界区执行的排他性

















