Java内存模型_基础
线程之间的通信机制有两种:
1、共享内存:线程之间共享程序的公共状态,通过写-读内存中的公共状态进行隐式的通信。
2、消息传递:线程之间没有公共状态,线程之间必须发送消息来显示的进行通信
同步:是指程序中用于控制不同线程间操作发生相对顺序的机制。
在共享内存并发模型里,同步是显式进行的。程序员必须显式指定某个方法或某段代码需要在线程之间互斥执行。在消息传递的并发模型里,由于消息的发送必须在消息的接收之前,因此同步是隐式进行的。
Java的并发采用的是共享内存模型,Java线程之间的通信总是隐式进行
在java中,所有实例域、静态域和数组元素存储在堆内存中,堆内存在线程之间共享。局部变量,方法定义参数和异常处理器参数不会在线程之间共享,它们不会有内存可见性问题,也不受内存模型的影响
内存不可见:是用于共享变量的值,没有及时刷新到主内存当中
Java内模型抽象结构示意图,如下
线程A与线程B之间要通信的话,必须要经历下面两个步骤。
1、首先,线程A把本地内存A中更新过的共享变量刷新到主内存中去。
2、然后,线程B到主内存中去读取线程A之前已更新过的共享变量。
这两个步骤实质上是线程A在向线程B发送消息,而且这个通信过程必须要经过主内存。JMM通过控制主内存与每个线程的本地内存之间的交互,来为java程序员提供内存可见性保证。
写缓冲区:它可以保证指令流水线持续运行,它可以避免由于处理器停顿下来等待向内存写入数据而产生的延迟
处理器上的写缓存区,仅仅对它所在的处理器可见。这对内存操作的执行顺序产生重要的影响:处理器对内存的读/写操作的执行顺序,不一定与内存实际发生的读/写操作顺序一致
从内存操作实际发生的顺序来看,直到处理器A执行A3来刷新自己的写缓存区,写操作A1才算真正执行了。虽然处理器A执行内存操作的顺序为:A1->A2,但内存操作实际发生的顺序却是:A2->A1。此时,
处理器A的内存操作顺序被重排序了
为了保证内存可见性,java编译器在生成指令序列的适当位置会插入内存屏障指令来禁止特定类型的处理器重排序。JMM把内存屏障指令分为下列四类:
屏障类型 | 指令示例 | 说明 |
LoadLoad Barriers | Load1; LoadLoad; Load2 | 确保Load1数据的装载,之前于Load2及所有后续装载指令的装载。 |
StoreStore Barriers | Store1; StoreStore; Store2 | 确保Store1数据对其他处理器可见(刷新到内存),之前于Store2及所有后续存储指令的存储。 |
LoadStore Barriers | Load1; LoadStore; Store2 | 确保Load1数据装载,之前于Store2及所有后续的存储指令刷新到内存。 |
StoreLoad Barriers | Store1; StoreLoad; Load2 | 确保Store1数据对其他处理器变得可见(指刷新到内存),之前于Load2及所有后续装载指令的装载。StoreLoad Barriers会使该屏障之前的所有内存访问指令(存储和装载指令)完成之后,才执行该屏障之后的内存访问指令。 |
StoreLoad Barriers是一个“全能型”的屏障,它同时具有其他三个屏障的效果。现代的多处理器大都支持该屏障(其他类型的屏障不一定被所有处理器支持)。执行该屏障开销会很昂贵,因为当前处理器通常
要把写缓冲区中的数据全部刷新到内存中。
happens-before:在JMM中,如果一个操作需要对另外一个操作可见,那么这两个操作(可以在同一个线程之内,也可以不在同一个线程之内)之间必须要存在happens-before关系。
happens-before规则:
- 程序顺序规则:一个线程中的每个操作,happens- before 于该线程中的任意后续操作。
- 监视器锁规则:对一个监视器锁的解锁,happens- before 于随后对这个监视器锁的加锁。
- volatile变量规则:对一个volatile域的写,happens- before 于任意后续对这个volatile域的读。
- 传递性:如果A happens- before B,且B happens- before C,那么A happens- before C。
两个操作之间具有happens-before关系,并不意味着前一个操作必须要在后一个操作之前执行!happens-before仅仅要求前一个操作(执行的结果)对后一个操作可见,且前一个操作按顺序排在第二个操作之前。
有了这些基础之后,我们在继续往下分析
转载于:https://www.cnblogs.com/prayers/p/7478668.html
Java内存模型_基础相关推荐
- 支撑Java内存模型的基础原理 西安尚学堂
指令重排序 在执行程序时,为了提高性能,编译器和处理器会对指令做重排序.但是,JMM确保在不同的编译器和不同的处理器平台之上,通过插入特定类型的Memory Barrier来禁止特定类型的编译器重排序 ...
- 全面理解java内存模型_深入理解Java内存模型(八)——总结
处理器内存模型 顺序一致性内存模型是一个理论参考模型,JVM和处理器内存模型在设计时通常会把顺序一致性内存模型作为参照.JVM和处理器内存模型在设计时会对顺序一致性模型做一些放松,因为如果完全按照顺序 ...
- java if在内存中_全面理解Java内存模型
Java 内存模型的抽象 在 java 中,所有实例域.静态域和数组元素存储在堆内存中,堆内存在线程之间共享(本文使用"共享变量"这个术语代指实例域,静态域和数组元素).局部变量( ...
- Java内存模型终于能讲明白啦,建议收藏!
作者:zhisheng http://www.54tianzhisheng.cn/2018/02/28/Java-Memory-Model/ 前提 <深入理解 Java 内存模型>程晓明著 ...
- 深入理解 Java 内存模型(转载)
摘要: 原创出处 http://www.54tianzhisheng.cn/2018/02/28/Java-Memory-Model/ 「zhisheng」欢迎转载,保留摘要,谢谢! 0. 前提 &l ...
- Java高并发编程(三):Java内存模型
1 Java内存模型的基础 在并发编程里,需要处理两个问题: 线程之间如何通信 线程之间如何同步. 通信指的是线程之间以何种机制来交换信息.在命令式编程里中,线程之间的通信机制有两种:共享内存和消息传 ...
- 深入理解 Java内存模型
深入理解 Java内存模型 原文地址:http://www.54tianzhisheng.cn/2018/02/28/Java-Memory-Model/ 本文主要内容有 Java 内存模型的基础.重 ...
- blp模型 上读下写_Java高并发编程(三):Java内存模型
1 Java内存模型的基础 在并发编程里,需要处理两个问题: 线程之间如何通信 线程之间如何同步. 通信指的是线程之间以何种机制来交换信息.在命令式编程里中,线程之间的通信机制有两种:共享内存和消息传 ...
- 深入理解 Java 内存模型 JMM
前提 <深入理解 Java 内存模型>程晓明著,该书在以前看过一遍,现在学的东西越多,感觉那块越重要,于是又再细看一遍,于是便有了下面的读书笔记总结.全书页数虽不多,内容讲得挺深的.细看的 ...
最新文章
- (一次性搞定)ORB_SLAM2地图保存与加载
- 计算机网络大一上学期期末考试试题及答案,大一第一学期期末计算机考试题及答案)...
- python zipfile 模块下中文乱码 '╡┌╥╗╒┬_╒╨▒Ω╣½╕µ.docx'
- python替换excel指定字符串_【python】替换指定内容,excel数据预处理
- python各种岗位薪资_python编程语言岗位薪资真不是盖的
- java 事件类型_Spring框架中有哪些不同类型的事件?
- 机器学习实战 | 数据探索(缺失值处理)
- 第6章 见缝插圆(《C和C++游戏趣味编程》配套教学视频)
- 优化函数、学习速率 与反向传播算法
- 为什么单独循环中的元素加法比组合循环中的要快得多?
- 声网 视频通话SDK小结
- 现在移动端还用rem吗?nonono
- PPT图片别再直接插入,这样处理一下,让你的PPT秒变高逼格
- 如何看懂照片的直方图?
- 小程序手机号码中间四位隐藏
- 13_冒泡算法(附完整java代码)
- re学习笔记(48)BUUCTF-re-[VN2020 公开赛]CSRe
- 格式化数字,逢千位数加逗号
- 实验9-9 有理数比较(10 分)
- DataX实践趟坑大全
热门文章
- MinGW - Minimalist GNU for Windows
- printf的两个需要注意的问题:无符号整数和64位整数
- [NodeJs] 如何使用nodejs对base64进行编解码?
- React开发(277):ant design time刚进入页面时间重置
- [vue] vue项目有使用过npm run build --report吗?
- [vue]vue渲染模板时怎么保留模板中的HTML注释呢?
- 前端学习(2306):react之组件使用
- 前端学习(2247)为什么用git-new
- “约见”面试官系列之常见面试题之第五十五篇之清除浮动的方法(建议收藏)
- plsql轻量版记录类型1