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

为什么会有JMM?从0到1一次性说清楚

JMM(Java Memory Model)是一种规范,定义了在多线程环境下Java程序中的内存访问行为。JMM保证了在多线程环境下程序的正确性,同时也允许编译器和处理器对指令进行优化,以提高程序的性能。

Java线程之间的通信由Java内存模型(简称JMM)控制,从抽象的⻆度来说,JMM定义了线程和主内存之间的抽象关系。JMM的抽象示意图如图所示:

 对于每⼀个线程来说,栈都是私有的,⽽堆是共有的。也就是说在栈中的变量(局部变量、⽅法定义参数、异常处理器参数)不会在线程之间共享,也就不会有内存可⻅性的问题,也不受内存模型的影响。⽽在堆中的变量是共享的,称为共享变量

所以,内存可⻅性是针对的共享变量

既然堆是共享的,为什么在堆中会有内存不可⻅问题?

这是因为现代计算机为了⾼效,往往会在⾼速缓存区中缓存共享变量,因为cpu访问缓存区⽐访问内存要快得多。

线程之间的共享变量存在主内存中,每个线程都有⼀个私有的本地内存,存储了该线程以读、写共享变量的副本。本地内存是Java内存模型的⼀个抽象概念,并不真实存在。它涵盖了缓存、写缓冲区、寄存器等。

Java线程之间的通信由Java内存模型(简称JMM)控制,从抽象的⻆度来说,JMM定义了线程和主内存之间的抽象关系。JMM的抽象示意图如图所示:

 从图中可以看出:
1. 所有的共享变量都存在主内存中。
2. 每个线程都保存了⼀份该线程使⽤到的共享变量的副本。
3. 如果线程A与线程B之间要通信的话,必须经历下⾯2个步骤:

i. 线程A将本地内存A中更新过的共享变量刷新到主内存中去。
ii. 线程B到主内存中去读取线程A之前已经更新过的共享变量。

所以,线程A⽆法直接访问线程B的⼯作内存,线程间通信必须经过主内存。

注意,根据JMM的规定,线程对共享变量的所有操作都必须在⾃⼰的本地内存中进⾏,不能直接从主内存中读取。

那么怎么知道这个共享变量的被其他线程更新了呢?这就是JMM的功劳了,也是JMM存在的必要性之⼀。JMM通过控制主内存与每个线程的本地内存之间的交互,来提供内存可⻅性保证。

Java中的volatile关键字可以保证多线程操作共享变量的可⻅性以及禁⽌指令重排序,synchronized关键字不仅保证可⻅性,同时也保证了原⼦性(互斥性)。在更底层,JMM通过内存屏障来实现内存的可⻅性以及禁⽌重排序。为了程序员的⽅便理解,提出了happens-before,它更加的简单易懂,从⽽避免了程序员为了理解内存可⻅性⽽去学习复杂的重排序规则以及这些规则的具体实现⽅法。

happens-before 谈谈 JMM的happens-before_众乐乐_2016的博客-CSDN博客  

JMM与Java内存区域划分的区别与联系

上⾯两⼩节分别提到了JMM和Java运⾏时内存区域的划分,这两者既有差别⼜有联系:

区别:两者是不同的概念层次。JMM是抽象的,他是⽤来描述⼀组规则,通过这个规则来控制各个变量的访问⽅式,围绕原⼦性、有序性、可⻅性等展开的。⽽Java运⾏时内存的划分是具体的,是JVM运⾏Java程序时,必要的内存划分。

联系:都存在私有数据区域和共享数据区域。⼀般来说,JMM中的主内存属于共享数据区域,他是包含了堆和⽅法区;同样,JMM中的本地内存属于私有数据区域,包含了程序计数器、本地⽅法栈、虚拟机栈。

实际上,他们表达的是同⼀种含义


http://www.kler.cn/news/9927.html

相关文章:

  • Adaptive AUTOSAR——State Management(VRTE 3.0 R21-11)
  • 笔记 | python蓝桥算法复习(预习)基础知识
  • 快排非递归 归并排序
  • spring(七):事务操作
  • docker 安装nocas
  • 亚马逊云科技Amazon Linux 2023正式发布,将为您提供长期支持
  • 使用Xftp连接Windows7虚拟机
  • webgl-图形非矩阵旋转
  • GooglePlay马甲包过审详细流程
  • Java基础(六)面向对象编程(进阶)
  • 2023-04-14 算法面试中常见的查找表问题
  • Available-Python-Tuf
  • ChatGPT大规模封号+停止注册?最火概念会凉吗?
  • 【Camera HW介绍】
  • AI绘画——Stable Diffusion模型,变分自编码器(VAE)模型 , lora模型——调配设置与分享
  • shell的简单信息-执行、变量命名、变量的数据类型
  • git 命令:工作日常使用
  • 基于CBC、ECB、CTR、OCF、CFB模式的AES加密算法
  • 洛谷 P1341 无序字母对
  • Monitor方案MT9800学习笔记(三) —— 点屏(V-by-One信号接口)
  • MybatisPlus <= 3.5.3.1 TenantPlugin 组件 存在 sql 注入漏洞(CVE-2023-25330)
  • 测试:腾讯云轻量4核8G12M服务器CPU流量带宽系统盘
  • pytorch进阶学习(三):在数据集数量不够时如何进行数据增强
  • 花30分钟,我用ChatGPT写了一篇2000字文章(内附实操过程)
  • 【LeetCode】剑指 Offer 49. 丑数 p240 -- Java Version
  • JavaScript 基础入门速成上篇
  • GPT、科技、人类的生产、知识与未来(下)
  • IO流复习
  • 算法题:图的表示形式与遍历框架
  • k8s 磁盘不够用,docker数据迁移 导致 /tmp Permission denied,docker优化日志 日志切割, 日志自动删除