JMM Java 内存模型(Java Memory Model)

📅 2026/7/13 13:12:34
JMM Java 内存模型(Java Memory Model)
目录一、JMM 是什么核心分层模型主内存 工作内存二、并发三大特性 JMM 对应的问题1. 可见性 Visibility2. 原子性 Atomicity3. 有序性 Ordering三、JMM 核心happens-before 先行发生原则四、内存屏障volatile 底层实现五、synchronized 在 JMM 的语义六、volatile 关键特性总结DCL 单例为什么必须加 volatile七、JMM 与 CPU 缓存一致性八、易混淆区分九、高频面试精简考点一、JMM 是什么JMM 是一套抽象规范定义了多线程环境下线程如何访问共享变量变量在主内存、工作内存之间的读写交互规则可见性、原子性、有序性三大并发问题解决方案注意JMM ≠ JVM 运行时数据区堆 / 栈 / 方法区它是逻辑模型不是物理内存划分。核心分层模型主内存 工作内存主内存Main Memory共享变量存放处所有线程共享对应堆中实例字段、静态变量。工作内存Working Memory每个线程私有线程操作变量只能拷贝副本到工作内存读写不能直接操作主内存。 对应虚拟机栈局部变量、寄存器、CPU 缓存。交互流程主内存 --(读写同步)-- 线程工作内存副本线程修改变量步骤从主内存拷贝变量副本到工作内存在工作内存读写副本刷新副本写回主内存时机不固定无同步会延迟二、并发三大特性 JMM 对应的问题1. 可见性 Visibility问题A 线程修改副本后没立刻刷回主内存B 线程看不到最新值。 解决方案volatile、synchronized、Lock2. 原子性 Atomicity问题多步操作被打断如i 读 加 写三步非原子多线程交错导致数据错乱。 解决方案synchronized、Lock、Atomic原子类3. 有序性 Ordering问题CPU / 编译器指令重排代码书写顺序和实际执行顺序不一致多线程出现诡异 bug。 重排三种编译器重排、CPU 指令重排、内存屏障重排。 解决方案volatile禁止前后重排、synchronized、happens-before三、JMM 核心happens-before 先行发生原则不用锁 /volatile 也能天然保证有序、可见8 条规则程序顺序规则单线程内前面代码 happens-before 后面代码监视器锁规则unlock 锁 happens-before 后续同一个 lock 锁volatile 变量规则对 volatile 写 happens-before 后续对该变量读线程启动规则start()happens-before 线程内所有操作线程终止规则线程内所有操作 happens-beforejoin()返回中断规则interrupt()调用 happens-before 检测中断代码对象终结规则对象初始化完成 happens-beforefinalize()传递性A hb BB hb C → A hb C只要满足 happens-before前操作对后操作可见、有序。四、内存屏障volatile 底层实现volatile 通过插入内存屏障禁止重排四种屏障LoadLoad读 1LoadLoad读 2 → 读 1 先执行完再读 2StoreStore写 1StoreStore写 2 → 写 1 刷新主存再写 2LoadStore读 1LoadStore写 2 → 读完再写StoreLoad写 1StoreLoad读 2开销最大volatile 写后必加volatile 读写屏障规则写 volatile前面所有读写不能重排到写之后写完插入 StoreLoad 屏障读 volatile后面所有读写不能重排到读之前五、synchronized 在 JMM 的语义原子性临界区代码同一时间仅一个线程执行可见性加锁 lock清空工作内存副本从主内存重新加载变量解锁 unlock把工作内存修改全部刷新回主内存有序性临界区内代码不会和外部指令跨锁重排满足监视器 hb 规则六、volatile 关键特性总结保证可见性写后立刻刷主存读时强制从主存加载保证有序性禁止指令重排不保证原子性复合操作i依旧线程不安全 适用场景状态标记、双重检查锁 DCL 单例DCL 单例为什么必须加 volatile不加 volatile 时对象创建三步会被重排分配内存引用赋值给 instance初始化对象 重排后顺序 1→2→3其他线程拿到半初始化的 instance出现空指针 / 脏数据。 volatile 禁止 2、3 重排解决问题。七、JMM 与 CPU 缓存一致性现代 CPU 多级缓存 (L1/L2/L3)硬件层面有缓存一致性协议 (MESI)但硬件开销大。 JMM 在语言层面屏蔽不同 CPU 硬件差异统一一套并发内存语义让 Java 跨平台并发行为一致。八、易混淆区分JMM语言内存模型并发规范解决多线程可见 / 原子 / 有序JVM 运行时数据区堆、虚拟机栈、本地方法栈、程序计数器、元空间是内存物理划分硬件内存模型CPU 缓存、MESI 缓存协议底层硬件实现九、高频面试精简考点i 线程不安全原因无原子性、无可见性、指令重排volatile 和 synchronized 区别volatile 轻量无原子synchronized 独占锁三者都保证happens-before 是什么JMM 的有序可见判断依据内存屏障作用阻止指令重排强制刷新缓存DCL 单例 volatile 作用防止对象初始化指令重排