Java内存模型(JMM)通过主内存与线程本地工作内存的“拷贝→操作→回写”机制保障可见性;主内存存共享变量,工作内存为逻辑抽象,变量交互需经read、load、use、assign、store、write、lock、unlock八种原子操作;volatile、synchronized和final提供不同同步语义,线程间通信必须通过主内存中转并依赖happens-before规则保证顺序。

主内存和本地工作内存之间的数据交互,是Java内存模型(JMM)保障多线程可见性的核心机制。它不对应物理内存的某一块,而是为描述线程行为抽象出来的逻辑划分:主内存存所有共享变量,每个线程有自己的本地工作内存(含变量副本),线程不能直接读写主内存,必须通过“拷贝→操作→回写”流程完成访问。
主内存与工作内存不是物理内存映射
主内存大致对应JVM堆和方法区中存储的实例字段、静态字段、数组元素;工作内存并非JVM运行时数据区中的某一部分,也不是CPU缓存的直译——它是JMM虚构的概念,可能体现为寄存器、L1/L2缓存、写缓冲区,甚至编译器优化后的临时存储。关键在于:它的存在是为了定义线程间如何交换数据,而不是描述硬件布局。
例如,一个 static int count = 0 存在主内存;线程A执行 count++ 前,必须先把 count 的当前值从主内存读取并加载到自己的工作内存中,再运算,最后写回主内存。这个过程本身不是原子的。
变量交互必须经过八种原子操作
JMM用8个不可分割的操作来规范主内存与工作内存之间如何传递数据:
- read:从主内存读取变量值
- load:把 read 得到的值放入工作内存变量副本
- use:把工作内存中的变量值传递给执行引擎
- assign:把执行引擎返回的结果赋值给工作内存变量
- store:把工作内存变量值传送到主内存
- write:把 store 传来的值写入主内存变量
- lock:对主内存变量加锁(标识为线程独占)
- unlock:释放主内存变量锁
这些操作必须遵循特定规则,比如 read 和 load 必须连续执行,中间不能插入其他操作;store 和 write 同理。违反规则就可能破坏可见性或一致性。
同步机制决定何时刷新与重载
普通变量没有强制同步策略,线程可能长期使用工作内存中的旧值。真正触发主内存与工作内存同步的,是JMM提供的同步语义:
- volatile 变量:每次 use 前强制执行 read + load(从主内存重新加载);每次 assign 后强制执行 store + write(立即写回主内存),并插入内存屏障防止重排序
- synchronized 块:进入时清空工作内存中相关变量副本(等效于丢弃旧值),退出时将修改过的变量全部 store + write 回主内存
- final 字段:在构造方法内正确初始化后,其值能保证对其他线程“安全发布”,即无需额外同步也能看到最终值
注意:volatile 能保证单次读/写的可见性,但像 counter++ 这类复合操作仍需 synchronized 或 AtomicInteger 才能保证原子性。
线程通信只能通过主内存中转
线程A无法访问线程B的工作内存,哪怕它们操作的是同一个变量。如果线程A修改了变量并写回主内存,线程B要看到新值,必须重新从主内存加载该变量——这中间没有自动通知机制,是否及时加载取决于是否有 happens-before 关系约束。
例如,线程A在 synchronized 块中修改变量后释放锁,线程B随后获取同一把锁,这时JMM保证线程B进入临界区前会看到线程A写入的所有结果。这种顺序保障,正是靠锁的 unlock → lock happens-before 规则实现的,而不是靠轮询或延迟。

















