jmm和volatile的核心是解决多线程下的可见性与有序性问题:因cpu缓存不一致和jit优化导致主线程修改running=false后子线程仍读取旧值,volatile通过强制主内存读写和内存屏障确保修改立即可见且禁止重排序,但不保证复合操作原子性。

学Java内存模型(JMM)和volatile,关键不是背概念,而是搞清“为什么需要它”——从CPU缓存、线程调度、JIT优化这些真实瓶颈出发,再回看代码行为,才能真正理解。
先从一个跑不起来的flag开始
写两行最简单的代码:
private static boolean running = true;
while (running) { /* 空循环 */ }
主线程改running = false,工作线程却卡在循环里出不来。这不是逻辑错,是硬件和JVM共同“联手”造成的可见性失效:一个线程改了主内存,另一个线程还在用自己缓存里的旧值,甚至JIT还可能把running优化进寄存器,彻底不读内存。volatile就是为解决这类问题而生的。
抓住JMM的三个锚点:主内存、工作内存、交互操作
JMM不是物理内存图,而是一套规则,它定义了:
- 所有变量都存在主内存(共享)
- 每个线程有自己的工作内存(私有副本)
- 读写必须走8个原子操作链:read→load→use / assign→store→write
volatile的作用,就是在read/load和assign/store环节加了强制约束:每次读必须从主内存取,每次写必须立刻刷回主内存,并插入内存屏障防止重排序。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
重点理解volatile“保证什么、不保证什么”
它只做两件事:
- 可见性:一个线程写,其他线程能立即看到最新值
- 有序性:禁止对volatile变量的读写与前后指令重排序(通过内存屏障实现)
但它不保证原子性。比如count++(读-改-写三步),即使count是volatile,依然可能丢失更新。这时候就得用AtomicInteger或synchronized。
动手验证比看十遍文档管用
写个最小可复现例子,用jconsole或jstack观察线程状态,再加volatile前后对比行为;用JITWatch看是否触发了去优化(deoptimization);甚至用Unsafe.getAndSetInt模拟底层store-store屏障效果。只有看到“不加volatile时死循环,加了就退出”,你才算真正看见了JMM在运行。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










