Java内存模型(JMM)

1.背景

JMM(Java Memory Model)的提出,主要基于以下的几种原因:

  1. 不同操作系统平台的内存模型不同,而Java又想做到Write Once Run Everywhere(即跨平台),那么必须要自己提供一套内存模型以屏蔽不同操作系统在内存模型方面的差异。
  2. 由于除了编译器层面可以进行指令重排外,处理器层面也可以,尽管指令重排在一定程度上能够提升程序运行的效率,但这仅限于单线程环境下,一旦处在多线程环境,这种指令重排带来的更多的是并发性问题(比如多级缓存与内存中的数据不一致),而Java又是多线程语言,那么就会存在多线程编程。为了保证开发者编写的并发程序能够按照预期安全地执行,Java必须提出一套并发编程相关的规范(比如happens-before原则)来解决多线程环境下的可能存在的并发性问题。

2.内容

2.1 内存规范

2.1.1 内存抽象

图片来源:https://www.cnblogs.com/theRhyme/p/9399881.html

  • 本地/工作内存:每个线程私有且独占,不可跨线程访问的物理内存区域。存放了共享变量的副本。
  • 主内存:线程间共享的逻辑内存区域(并不真实存在)。存放所有线程创建的实例对象,包括:成员变量、局部变量、类信息、常量、静态变量等。线程间通信必须借助主内存来进行。

2.1.2 内存操作

图片来源:https://blog.csdn.net/qq_39940205/article/details/120642838

下面的8种操作主要用于主内存与工作内存的数据交互:

  • 锁定(lock):将主内存中的一个共享变量标记为线程独享变量
  • 读取(read):将主内存中的一个共享变量传递到线程的工作内存中。
  • 载入(load):将从主存(通过read)读到的共享变量装载进工作内存中的相应的共享变量副本中。
  • 使用(use):将共享变量的副本传递给执行引擎,供其使用。(每次需要用到该变量时,都会执行该指令)
  • 赋值(assign):将从执行引擎接收到的结果值赋值给共享内存的副本。(每次的赋值操作均会调用该指令)
  • 存储(store):将共享变量的副本传递回主内存中。
  • 写入(write):将接收到的共享变量的副本(新修改的共享变量)写回主内存中的相应的共享变量中。
  • 解锁(unlock):将主内存中的一个共享变量线程独享变量的状态标记取消。

注:
JMM规范中并没有明确说明readstore将读到的共享变量(副本)存放在工作内存/主内存的什么地方,但是肯定没有存发在共享变量(副本)对应的槽位上(类似于找一个地方暂存一下数据的意思),因为它需要loadwrite指令正式存放到相应的变量槽位上去。

要求

  1. 同一时间,只能有一个线程持有某一共享变量的锁(通过lock指令获取),获得锁的线程可以多次加锁(同一个),但是释放锁时需要释放同等次数(类似于ReentrantLock)。
  2. 使用共享变量之前,必须先读取载入,即不允许在工作内存中读取一个凭空诞生(主内存中没有)的变量。
  3. 不允许写回一个没有赋值共享变量副本。(这样做你觉得有意义?😅)
  4. …(此处省略很多字)

2.2 并发规范

2.2.1 happends-before原则

一句话概括就是:前一个操作的结果对后一个操作是可见的,无论这两个操作是否处在同一个线程里。

8项原则

  1. 程序顺序原则:在同一个线程内的代码中,写在前面的代码happens-before写在后面的代码
  2. 锁规则加锁happens-before释放锁
  3. volatile规则:对于一个volatile变量的写操作happens-before volatile变量的读操作。(该原则并不是说你只能先写后读一个volatile变量,而是说,前一个操作如果是写入volatile变量的操作,那么该volatile变量的新值对于后续的volatile读操作一定是可见的)
  4. start规则线程的start()动作happens-before线程内的每个动作
  5. join规则线程内的所有动作happens-before线程的join()动作
  6. interrupt规则对线程调用interrupt() happens-before线程自己检测到中断事件的发生
  7. finalize规则一个对象的构造函数的执行、结束和返回happens-before这个对象finalize()方法的开始
  8. 传递性A happens-before BB happens-before C,那么就有A happens-before C

3.注意事项

3.1 JMMJVM内存结构的区别

  • JMM:与Java并发编程相关,抽象了线程与主内存的关系,规定了并发相关的原则和规范,以简化多线程编程,增强程序的可移植性。
  • JVM内存结构:与JVM运行时区域相关,定义了JVM如何分区存储不同类型的数据。

3.2 happens-beforeJMM的关系

图片来源:http://wxweven.win/2016/10/15/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3Java%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B%EF%BC%88%E4%B8%80%EF%BC%89%E2%80%94%E2%80%94%E5%9F%BA%E7%A1%80%E7%AF%87/
JMM通过自行禁用处理器的若干重排序规则或者直接禁用某种类型的处理器来实现它向程序猿发出的happens-before几点保证,因为处理器的重排序规则在并发环境下可能会产生未知差错从而使得happens-before失去保证,所以必须要根据实际的运行情况进行适当的禁用。

4.补充

4.1 并发编程的三大重要特性

  1. 原子性:一次操作或者多个操作要么全都执行,要么全都不执行。(这里不包括执行失败后回滚的情况,即并发编程的原子性 ≠ 事务性的原子性)
  2. 可见性:当一个线程对某一个共享变量进行了修改,那么其他线程将能够立即看到修改后的新值。
  3. 有序性:因为编译器和处理器对代码进行指令重排序的缘故,你所编写的代码的顺序不一定就是代码实际的执行顺序。

参考文档

JMM(Java 内存模型)详解

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/844755.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

断开自定义模块与自定义库的链接

断开自定义模块与自定义库的链接 1、断开模块与库的链接 1、断开模块与库的链接 如果摸个库文件添加到模型中,无法“Disable Link”时,可以使用save_system命令进行断开到模型中用户定义的库模块的链接; 参考链接: 传送门 save…

js之简单分页

一直以来有许多兄弟问我分页怎么写,我今天就来给大家讲解下分页的简单技巧,不过兄弟们也知道我不怎么喜欢打字,喜欢打代码,话不多说,直接上代码,直接上注释,gogogo!!&…

docker占用磁盘空间大小排查

首先进入到 /var/lib/docker/overlay2 目录下,查看谁占用的较多 cd /var/lib/docker/overlay2/du -s ./* | sort -rn | more再通过目录名查找容器名 docker ps -q | xargs docker inspect --format {{.State.Pid}}, {{.Id}}, {{.Name}}, {{.GraphDriver.Data.WorkDir}} | gre…

《C语言深度解剖》(16):C语言的文件读写操作

🤡博客主页:醉竺 🥰本文专栏:《C语言深度解剖》 😻欢迎关注:感谢大家的点赞评论关注,祝您学有所成! ✨✨💜💛想要学习更多C语言深度解剖点击专栏链接查看&…

EmmyLua注释详解

Lua EmmyLua 注解详解 Why 为了使 IDE 编码体验和强语言相近 让 IDE 提前发现编码错误 BUG 查找更方便 代码阅读更方便 建议 明确字段类型 明确字段访问修饰符 明确方法参数类型 善用 “:” 继承 “|” 或 ","多个 支持格式 –类 —class MY_TYPE[:PARENT_TYPE] [com…

rabbitmq的交换机类型以及他们的区别

RabbitMQ中有四种主要的交换机类型,它们是:Direct,Topic,Fanout,Headers。 Direct(直连交换机):接收到消息后,会将消息发送到与消息的routing key完全匹配的队列上。Dire…

n后问题 回溯笔记

问题描述 在nn格的棋盘上放置彼此不受攻击的n个皇后。 按照国际象棋的规则,皇后可以攻击与之处在同 一行或同一列或同一斜线上的棋子。n后问题等价于在nn格的棋盘上放置n个皇后,任何2个皇后不放在同一行或同一列或同一斜线上。 代码 import java.uti…

awtk踩坑记录一:awtk-web build.py编译过程笔记

工作需求,接触了awtk, 要求把界面部署到web上,期间因为各种编译问题卡的半死,提了不少issue, 经过几天补课,把项目的编译结构给摸了一遍,做个记录,也希望能帮到有同样问题的朋友。 之前python只是略接触过…

怎麼進行郵箱抓取以及郵箱抓取工具推薦

郵箱抓取是使用自動搜刮工具或腳本從網站、文檔或其他線上資源中提取電子郵件地址的過程。有適用於幾乎所有網站的通用搜索工具,也有為特定平臺量身定制的專用搜索工具。這種技術通常用於市場行銷、潛在客戶生成和數據收集等。 郵箱抓取的工作原理 它能解析網站的…

在 iCloud.com 上导入、导出或打印联系人

想将iPhone上的电话本备份一份到本地电脑上,发现iTunes好像只是音乐播放了,不再支持像电话本等功能,也不想通过其他第三方软件,好在可以通过iCloud进行导入导出。下面只是对操作过程进行一个图片记录而已,文字说明可以…

总是不能盈利?试着用这两个观点去学习现货白银的技巧

一进入现货白银市场,投资者都想着如何去找到现货白银交易的机会,学习现货白银投资的方法。其实这些都是手段,而最终的目的还是为我们的盈利服务。而对于盈利来说,其实胜率和风险报酬比才是影响盈利的重要因素,我们带着…

HTML中的基础标签(适合于新手)

若想进一步了解可到菜鸟教程HTML 1. div:用来布局&#xff0c;没有具体含义 <div><p>哈哈哈哈</p></div>2. hx:标题&#xff0c;分六级&#xff0c;会自动加粗&#xff0c;有默认字号 <h1>哈哈哈哈 </h1>3. p:连续的段落&#xff0c;相当…

centos8stream 编译安装 php-rabbit-mq模块

官方GitHub&#xff1a;https://github.com/php-amqp/php-amqp 环境依赖安装 dnf install cmake make -y 1.安装rabbitmq-c cd /usr/local/src/ wget https://github.com/alanxz/rabbitmq-c/archive/refs/tags/v0.14.0.tar.gz tar xvf v0.14.0.tar.gz cd rabbitmq-c-0.14.0/…

lambda函数实践

文章目录 1.简单实例2.lambda函数使用3.捕获列表的使用4.lambda表达式的应用 1.简单实例 2.lambda函数使用 3.捕获列表的使用 4.lambda表达式的应用 #include <iostream> #include <vector>using namespace std;/** 1.简单实例* 2.lambda函数使用* 3.捕获列表的…

不用写采集规则的网页采集软件

传统的网页采集工具采集网页数据&#xff0c;需要查看和研究网页代码&#xff0c;编写复杂繁琐的采集规则&#xff0c;对于有技术基础的人&#xff0c;配置一个采集规则也要花费不少时间&#xff0c;更何况对于不懂技术的普通用户来说&#xff0c;简直是一项不太可能完成的任务…

服务器内存与CPU要占用多少才合理?

一 通常服务器内存占用多少合理&#xff1f;cpu占用多少才合理&#xff1f; 1 通常配置范围建议&#xff1a; 建议CPU使用率不高于80%&#xff1b;内存使用率不高于80%&#xff1b; 注意&#xff1a;具体情况还需要根据服务器的实际负载和应用场景来判断。 2 内存使用率&…

备受推崇的公司文件加密文件推荐榜单

迄今为止&#xff0c;加密依然是最有效的用于保护数据、通讯安全的手段之一 在数字化时代&#xff0c;文件加密软件成为了保护个人和企业数据安全的重要工具。随着技术的不断进步&#xff0c;市场上涌现出了众多优秀的文件加密软件。 以下十款文件加密软件因其出色的性能、易…

新疆 | 金石商砼效率革命背后的逻辑

走进标杆企业&#xff0c;感受名企力量&#xff0c;探寻学习优秀企业领先之道。 本期要跟砼行们推介的标杆企业是新疆砼行业的龙头企业&#xff1a;新疆兵团建工金石商品混凝土有限责任公司&#xff08;以下简称&#xff1a;新疆金石&#xff09;。 从年产80万方到120万方&am…

【Python编程】给电脑安装最新的 Python3.12.3

笔者最近更换了新的Win11系统&#xff0c;安装最新的Python版本&#xff08;3.12.3&#xff09;尝尝鲜。据说这个版本存在一些漏洞&#xff0c;笔者将后续更新编程过程中的相关问题&#xff08;如果有&#xff09;。Python3.12.3的安装过程比较简单&#xff0c;在此进行说明。 …

MyBatisPlus的简单入门

文章目录 1.MybatisPlus的简介2.创建SpringBoot工程3.编写测试类 1.MybatisPlus的简介 MyBatisPlus&#xff08;简称MP&#xff09;是基于MyBatis框架基础上开发的增强型工具&#xff0c;旨在&#xff1a;简化开发、提高效率。 它对应的官方网址&#xff1a;链接 2.创建Sprin…