Java内存模型(JMM)

news/2024/10/22 7:48:35/

JMM(Java内存模型)

概念

Java 内存模型(Java Memory Model,JMM)定义了 Java 程序中的变量、线程如何和主存以及工作内存进行交互的规则。它主要涉及到多线程环境下的共享变量可见性、指令重排等问题,是理解并发编程中的关键概念。JMM的目的是为了解决多线程环境下的内存(本地内存)一致性问题。

在多线程的情况下,会出现多个线程对同一共享变量同时读取,但是这会产生脏读,不可重复读,幻读等问题。JMM 中定义的规则,控制了本地内存和主存中的交互,来保证内存可见性,这样也就知道这个变量正在被更改,保证变量的可见性。

例如:volatile 和 synchronized。

注意 JMM 和 JVM 运行时数据区 不是一个东西 ,JMM 是抽象的,他是一组规则。

指令重排序

系统执行代码的顺序不一定是你写的代码的顺序。

为什么要指令重排序?

计算机在执行过程中,为了提高性能,会对编译器和编译器做指令重排序。

为了提高利用率以及程序的性能, Java 虚拟机会在你这个指令还没完全执行完毕的时候,就去执行另外一个指令。这就是流水线技术

我们知道计算机在执行的时候都是一个个指令去执行,不同的指令可能操作的硬件不一样,在执行的过程中可能会产生中断,打个比方,两个指令a和b他们操作的东西各不相同,如果加载a的时候停顿了,b就加载不到,但是实际上它们互补影响,我也可以先加载b在加载a,所以指令重排是减少停顿的一种方法,这样大大提高了效率。

导致问题

指令重排序会导致乱序的问题。

指令重排序分三种:

  • 编译器优化重排,编译器在不改变单线程程序语义的前提下,重新安排语句的执行顺序。

  • 指令并行重排,现代处理器采用了指令级并行技术来将多条指令重叠执行。如果不存在数据依赖性(即后一个执行的语句无需依赖前面执行的语句的结果),处理器可以改变语句对应的机器指令的执行顺序。

  • 内存系统重排,由于处理器使用缓存和读写缓存冲区,这使得加载(load)和存储(store)操作看上去可能是在乱序执行,因为三级缓存的存在,导致内存与缓存的数据同步存在时间差。

由上面的三种重排序可以看出来,指令重排序可以保证串行语义一致(单线程情况下不会导致结果错误),但是多线程情况下,会导致结果出现问题。

JMM和顺序一致性

顺序一致性模型是一个理想化的内存模型,它假设所有线程的操作都是按照某种全局一致的顺序执行的,每个线程的操作都按照程序指定的顺序对所有线程可见。在顺序一致性模型中,不存在重排序、缓存和优化等问题,所有线程看到的内存状态都是一致的。

关键词 -- 执行顺序和写入顺序相同,共享变量对所有线程可见

JMM 和 顺序一致性模型的区别
重排序

JMM 是有重排序的,为了提高效率。顺序一致性模型完全按照写入顺序执行,没有重排序。

可见性

在JMM中,线程对共享变量的修改并不总是立即对其他线程可见。并且利用了某些方式去改变共享变量的可见性,例如:volatile,synchronized 等。

顺序一致性模型保证所有线程看到的内存状态都是一致的。


happens-before原则

ok 说了这么多 ,JMM 怎么保证在多线程情况下,结果不出错?靠的都是happen - before 原则。

对于编译器而言,只要不改变程序最终运行出的结果,无论怎么换顺序都行,这样 JMM 找到了平衡点。

内容
  1. 如果一个操作 happens-before 另一个操作,那么第一个操作的执行结果将对第二个操作可见,并且第一个操作的执行顺序排在第二个操作之前。

  1. 两个操作之间存在 happens-before 关系,并不意味着 Java 平台的具体实现必须要按照 happens-before 关系指定的顺序来执行。如果重排序之后的执行结果,与按 happens-before 关系来执行的结果一致,那么 JMM 也允许这样的重排序。

传递规则:如果 A happens-before B,且 B happens-before C,那么 A happens-before C;

总结

如果 A happens-before B,那么无论这两个操作在不在一个线程内,都要保证 A 对 B 可见。


http://www.ppmy.cn/news/1460447.html

相关文章

关于Speech processing Universal PERformance Benchmark (SUPERB)基准测试及衍生版本

Speech processing Universal PERformance Benchmark (SUPERB)是由台湾大学、麻省理工大学,卡耐基梅隆大学和 Meta 公司联合提出的评测数据集,其中包含了13项语音理解任务,旨在全面评估模型在语音处理领域的表现。这些…

电商秒杀系统-案例03-浏览统计的redis hash实现方式

前言 在本篇博文中,我们将探讨如何在一个博客网站上实现文章浏览次数的统计功能。通过使用Redis的hash数据结构,我们可以有效地记录和更新每篇文章的浏览次数。接下来,我将详细解释具体的实现方法。 目录 博客网站文章浏览次数统计简介使用…

GitHub Actions 手动触发方式

目录 前言 Star Webhook 手动触发按钮 前言 GitHub Actions 是 Microsoft 收购 GitHub 后推荐的一款 CI/​CD 工具早期可能是处于初级开发阶段,它的功能非常原生,甚至没有直接提供一个手动触发按钮一般的触发方式为代码变动(push 、pull…

Web3Tools - 助记词生成

Web3Tools - 助记词生成工具 本文介绍了一个简单的助记词生成工具,使用 React 和 Material-UI 构建。用户可以选择助记词的语言和长度,然后生成随机的助记词并显示在页面上 功能介绍 选择语言和长度: 用户可以在下拉菜单中选择助记词的语言&…

Centos中将UTC的时区改为CTS时区

date命令可以看到现在的时间以及时区,可以看到现在是UTC时区 而想要更改时区那么就要了解tzselect命令 tzselect 是一个 Linux 命令行工具,用于交互式地帮助用户选择并设置系统的时区。这个程序会通过一系列的问题引导用户,从而确定用户所在的…

el-tree

Vue.js 组件结构: 是一个 Vue.js 组件,它由一些 Vue 文件组成,包括模板(template)、脚本(script)和样式(style)。 模板部分定义了组件的结构和布局,包括树节点…

蓝桥杯EDA客观题

目录 前言 一、PCB类知识点和题目分析 1.电阻 2.电容 3.封装类 4.单位转换类 5.电路板结构类 6.PCB绘制规则 7.立创软件 8.PCB硬件 线性电源和开关电源 二、数电知识点和题目分析 1.门电路 2.逻辑代数 3.组合逻辑电路 4.触发器 5.时序逻辑电路 6.其他 三、模…

《十堂课学习 Flink》第九章:Flink Stream 的实战案例一:CPU 平均使用率监控告警案例

9.1 本章概述 本章的所有需求、设计、开发仅是模拟真实业务场景,因为实际业务需求、现场环境更加复杂,并且考虑到本系列课程本身就偏向于基础内容,因此这里我们对自己假设的业务场景进行设计与开发,整个流程虽然简单,…