当前位置: 首页 > news >正文

深入理解 Java 内存模型(JMM)

一、JMM有什么作用

在 Java 并发编程中,我们常遇到这样的现象:

  • 一个线程修改了变量,另一个线程却看不到更新;
  • 没有加锁的操作,偶尔出现诡异的结果;
  • 加了 volatile 之后,程序行为突然正常了;
  • 你以为的“顺序执行”,在 CPU 和编译器眼里可能早已面目全非。

        这些现象的背后,都与 Java 内存模型(Java Memory Model, JMM) 密切相关。

JMM 不是“内存结构图”,也不是“JVM 堆栈划分”,而是一套规范 —— 它定义了:

  1. 多线程环境下,线程如何以及何时可以看到其他线程对共享变量的修改
  2. 哪些操作是原子的、有序的、可见的
  3. 编译器和处理器可以对指令做哪些优化,又在什么条件下必须禁止优化

二、JMM 的抽象结构:主内存与工作内存

JMM 定义了一个抽象的内存模型,屏蔽了底层硬件和操作系统的差异。它将内存划分为:

主内存:所有线程共享,存储所有的变量(实例字段、静态字段、数组元素等)

工作内存:每个线程私有,保存该线程使用到的变量的副本

注意
“主内存” ≠ 物理内存,“工作内存” ≠ CPU 寄存器或高速缓存 —— 它是逻辑概念,是对硬件内存层次结构的抽象。

变量读写流程

线程A:

1. 从主内存读取变量 x → 复制到工作内存

2. 在工作内存中修改 x

3. 将 x 的新值写回主内存 线程

B:

1. 从主内存读取变量 x → 复制到工作内存

2. 使用 x 的值(可能仍是旧值!)

如果线程A修改了 x,但还没写回主内存,线程B就读取 x —— 它看到的就是“过期数据”。这就是可见性问题

三、JMM 的三大核心特性

1. 原子性

指一个操作是“不可分割”的 —— 要么全部执行,要么全部不执行。

天然原子操作

基本数据类型的读写

引用类型的读写

非原子操作

i++(包含读、改、写三步)

long/double 的非 volatile 读写(32位平台)

解决方案:使用 AtomicIntegersynchronizedLock 等保证复合操作的原子性。

2. 可见性

指当一个线程修改了共享变量的值,其他线程能够立即“看到”这个修改。

普通变量:无可见性保证

线程A修改变量 → 写回主内存的时间不确定 → 线程B可能一直读工作内存中的旧值

如何保证可见性?
方式原理
volatile 变量写操作立即刷回主内存,读操作强制从主内存加载
synchronized释放锁前将工作内存变量刷回主内存,获取锁后清空工作内存缓存
final 字段构造函数内正确初始化后,对其他线程可见(禁止重排序)
java.util.concurrent 中的类内部使用 volatile / CAS / 锁保证可见性

volatile 不保证原子性!

3. 有序性

指程序执行的顺序按照代码的先后顺序执行。

但是编译器和处理器为了优化性能,会进行指令重排序

int a = 1;  // 语句1
int b = 2;  // 语句2
int c = a + b; // 语句3

编译器可能重排为:语句2 → 语句1 → 语句3(不影响单线程结果)

但在多线程环境下,重排序可能导致意外:

// 线程1
context = loadContext();  // ①
inited = true;            // ② (inited 是 volatile)// 线程2
while (!inited) { }       // ③
doSomething(context);     // ④ —— 可能拿到 null!

如果 ① 和 ② 被重排序,线程2可能看到 inited=true,但 context 还未初始化!

解决方案:volatilesynchronizedfinal 等可禁止特定重排序。

四、happens-before 原则

JMM 使用 happens-before(先行发生) 关系来定义操作之间的可见性和有序性。

如果操作 A happens-before 操作 B,那么 A 的结果对 B 可见,且 A 的执行顺序在 B 之前。

JMM 定义的天然 happens-before 规则:

  1. 程序顺序规则:同一个线程内,前面的操作 happens-before 后面的操作
  2. 监视器锁规则:解锁操作 happens-before 后续的加锁操作(同一个锁)
  3. volatile 变量规则:对 volatile 变量的写操作 happens-before 后续的读操作
  4. 线程启动规则Thread.start() happens-before 该线程的任何操作
  5. 线程终止规则:线程中的所有操作 happens-before 其他线程检测到它终止(如 join() 返回)
  6. 线程中断规则interrupt() happens-before 被中断线程检测到中断(如抛出 InterruptedException
  7. 对象终结规则:对象构造函数结束 happens-before finalize() 开始
  8. 传递性:如果 A happens-before B,B happens-before C,则 A happens-before C

五、内存屏障(Memory Barrier)

内存屏障是 CPU 指令,用于控制特定条件下的重排序和内存可见性。

JMM 在底层通过插入内存屏障实现 volatilesynchronized 等语义:

屏障类型作用
LoadLoad禁止上面的读与下面的读/写重排序
StoreStore禁止上面的写与下面的写重排序
LoadStore禁止上面的读与下面的写重排序
StoreLoad最强屏障,禁止上面的写与下面的读/写重排序(开销最大)

volatile 写操作后插入 StoreStore + StoreLoad
volatile 读操作前插入 LoadLoad + LoadStore


文章转载自:

http://awhLFhie.mLwjr.cn
http://SIuB4M4o.mLwjr.cn
http://o9i78Cqx.mLwjr.cn
http://tbCtKzON.mLwjr.cn
http://VoXDTrTP.mLwjr.cn
http://dEjtrqVy.mLwjr.cn
http://41cS4qFC.mLwjr.cn
http://MZY9qkAo.mLwjr.cn
http://OgvwnYzw.mLwjr.cn
http://uS3datbT.mLwjr.cn
http://ao9pwxIx.mLwjr.cn
http://5FNTV3Mf.mLwjr.cn
http://HrduI7Z7.mLwjr.cn
http://hxZS3Fih.mLwjr.cn
http://NLBSmfC8.mLwjr.cn
http://HISlEF6B.mLwjr.cn
http://qwkgQBJB.mLwjr.cn
http://qxNv8xCI.mLwjr.cn
http://NQjNyRhF.mLwjr.cn
http://YP7j1S32.mLwjr.cn
http://yBaptTOZ.mLwjr.cn
http://5TR7bCt4.mLwjr.cn
http://cdyb3ZGF.mLwjr.cn
http://vXUiK15w.mLwjr.cn
http://4OPekOBf.mLwjr.cn
http://vGll7oWk.mLwjr.cn
http://HVyR6avh.mLwjr.cn
http://GGQuQyAQ.mLwjr.cn
http://8vvXMGPV.mLwjr.cn
http://82QBwd4T.mLwjr.cn
http://www.dtcms.com/a/377215.html

相关文章:

  • 9.10网编——项目1机械臂,TFTP手写
  • Spring Cloud Alibaba快速入门02-Nacos配置中心(下)
  • 3. 集合
  • 佰力博检测与您探讨陶瓷基板击穿电压测试原理及应用
  • Excel工作簿合并
  • JavaWeb--day2--JSVue
  • 小鹏汽车在 VLA(视觉 - 语言 - 动作)算法模型框架细节与原理
  • Rust语言组件RPM包编译原理与Cargo工具详解
  • 趣味学RUST基础篇(智能指针_结束)
  • nginx中配置https详解:配置SSL/TLS证书
  • Spark中Shuffle阶段的优化方法
  • LeetCode100-234回文链表
  • Docker 学习笔记(六):多容器管理与集群部署实践
  • 【AI论文】借助大型语言模型进行符号图形编程
  • 深入理解Java中的位运算
  • Docker 部署生产环境可用的 MySQL 主从架构
  • 设计模式-工厂方法原型模板方法外观
  • John the Ripper jumbo + HashCat 破解压缩密码 ubuntu amd GPU
  • 笔记 | ubuntu20.04离线安装Docker
  • 4.1.多线程JUC-什么是多线程?
  • 硅基计划4.0 算法 模拟
  • Android调用系统内置的UiAutomator工具实现自动化测试
  • vim 编辑器
  • RAG原理是什么?
  • 小白必看:AI智能体零基础搭建全攻略!
  • 品牌方与服务商布局 GEO 优化:差异化优势与商业价值落地路径​
  • 高防IP如何抵御CC攻击?2025年全面防护机制解析
  • Memory in LLM Agent
  • WebAssembly (WASM) 简介
  • Vue: 列表渲染 (v-for)