volatile 到底保证什么?指令重排怎么导致双重检查锁失效?happens-before 是什么?JMM 不是内存结构,而是并发编程的"交通规则"。
一、JMM 是什么
1.1 JMM vs JVM 内存结构
JVM 内存结构(运行时数据区):
堆、栈、方法区、程序计数器 → 物理内存划分
JMM(Java Memory Model,Java 内存模型):
描述多线程环境下变量的访问规则
不是物理内存划分,而是抽象的并发规则
JMM 核心:
每个线程有自己的工作内存(CPU 缓存/寄存器抽象)
所有线程共享主内存
线程不能直接读写主内存
线程只能操作工作内存中的副本
工作内存与主内存之间通过 save/load 同步
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Thread A │ │ Thread B │ │ Thread C │
│ ┌──────────┐ │ │ ┌──────────┐ │ │ ┌──────────┐ │
│ │工作内存 │ │ │ │工作内存 │ │ │ │工作内存 │ │
│ │ x = 0 │ │ │ │ x = 1 │ │ │ │ x = 0 │ │
│ └────┬─────┘ │ │ └────┬─────┘ │ │ └────┬─────┘ │
└──────┼───────┘ └──────┼───────┘ └──────┼───────┘
│ save/load │ save/load │ save/load
▼ ▼ ▼
┌──────────────────────────────────────────────┐
│ 主内存 │
│ x = 0 (初始值) │
└──────────────────────────────────────────────┘
问题:
Thread B 把 x 改成 1 → 写到工作内存 → 还没 save 到主内存
Thread A 读 x → 从工作内存读 → 还是 0 → 可见性问题!
2026/7/2大约 9 分钟