JMM是一套抽象规范,定义多线程下共享变量在主内存与工作内存间的读写、同步与可见性规则;它通过happens-before、volatile、synchronized等机制协同保障原子性、可见性与有序性。

JMM 不是物理内存结构,而是一套规范线程如何读写共享变量的抽象规则。它不自动保证原子性、可见性、有序性,而是通过 synchronized、volatile、final 等语义配合内存屏障,约束编译器、JVM 和 CPU 的行为,让开发者能写出可预期的并发代码。
原子性:操作不可被中断,但需主动保障
原子性指一个操作要么全部执行,要么完全不执行,中间不能被其他线程打断。Java 中基本类型(除 long/double 在旧 JVM 外)的单次读或写是原子的,但像 count++ 这类“读-改-写”复合操作不是原子的——它会被拆成多条字节码指令,多个线程交叉执行就会导致结果丢失。
- synchronized 通过互斥锁把临界区变成串行执行,使非原子操作整体具备原子性
- Lock 接口(如 ReentrantLock)提供更灵活的加锁方式,同样保障临界区原子性
- AtomicInteger 等原子类利用 CAS 指令在硬件层实现无锁原子更新
- volatile 不能解决原子性问题,哪怕只对一个 int 变量做自增,依然会出错
可见性:确保一个线程的修改对其他线程及时可见
可见性问题源于线程工作内存与主内存的分离。线程 A 修改了变量,若未同步回主内存,线程 B 可能一直读取自己工作内存中的旧值。JMM 要求某些操作强制刷新或重载数据,打破缓存不一致。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- synchronized 加锁时清空工作内存副本,解锁前强制刷回主内存,天然支持可见性
- volatile 写操作后立即写入主内存,读操作前强制从主内存加载,破除本地缓存
- final 字段 在构造器内完成初始化后,借助隐式内存屏障,确保对象发布后其他线程看到正确值
- 普通变量无任何保障,即使只赋一次值,也可能因 JIT 优化或缓存延迟导致其他线程看不到
有序性:限制指令重排序,维持逻辑先后关系
CPU 和编译器为提升性能会重排指令,只要不影响单线程语义即可。但在多线程下,重排可能破坏依赖逻辑,比如“先设 flag = true,再初始化 data”,若重排为先初始化 data 再设 flag,另一线程可能读到未初始化的 data。
立即学习“Java免费学习笔记(深入)”;
- volatile 在读写前后插入内存屏障(如 LoadLoad、StoreStore),禁止特定方向的重排序
- synchronized 的 monitorenter/monitorexit 指令自带屏障语义,禁止临界区内外指令穿插
- happens-before 规则 是 JMM 定义的逻辑顺序约束,例如程序顺序规则、监视器锁规则、volatile 变量规则等,共同构成跨线程操作的可见性与有序性基础
- 没有同步手段时,重排序真实存在,且不同 CPU 架构表现不一(x86 强序,ARM 弱序)
理解 JMM 的关键,在于认清它提供的是工具和边界,而不是魔法。用错 volatile 去做计数、漏掉 synchronized 包裹复合逻辑、忽略 final 正确初始化时机,都会让并发程序悄然出错。不复杂但容易忽略。

















