volatile保证可见性及重排序方法


Posted in Java/Android onAugust 05, 2022

一、JMM的内存可见性保证

按程序类型,Java程序的内存可见性保证可以分为下列3类:

单线程程序:单线程程序不会出现内存可见性问题。编译器、runtime和处理器会共同确保单线程程序的执行结果与该程序在顺序一致性模型中的执行结果相同。

正确同步的多线程程序:正确同步的多线程程序的执行将具有顺序一致性(程序的执行结果与该程序在顺序一致性内存模型中的执行结果相同)。这是JMM关注的重点,JMM通过限制编译器和处理器的重排序来为程序员提供内存可见性保证。

未同步/未正确同步的多线程程序:JMM为它们提供了最小安全性保障:线程执行时读取到的值,要么是之前某个线程写入的值,要么是默认值未同步程序在JMM中的执行时,整体上是无序的,其执行结果无法预知。 JMM不保证未同步程序的执行结果与该程序在顺序一致性模型中的执行结果一致。

二、volatile的内存语义

1、volatile的特性

可见性:对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写入。

原子性:对任意单个volatile变量的读/写具有原子性,但类似于volatile++这种复合操作不具有原子性(基于这点,我们通过会认为volatile不具备原子性)。volatile仅仅保证对单个volatile变量的读/写具有原子性,而锁的互斥执行的特性可以确保对整个临界区代码的执行具有原子性。

有序性:对volatile修饰的变量的读写操作前后加上各种特定的内存屏障来禁止指令重排序来保障有序性。

volatile 写-读的内存语义:

当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量值刷新到主内存。

当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效,线程接下来将从主内存中读取共享变量。

2、volatile可见性实现原理

JMM内存交互层面实现:volatile修饰的变量的read、load、use操作和assign、store、write必须是连续的,即修改后必须立即同步回主内存,使用时必须从主内存刷新,由此保证volatile变量操作对多线程的可见性。

硬件层面实现:通过lock前缀指令,会锁定变量缓存行区域并写回主内存,这个操作称为“缓存锁定”,缓存一致性机制会阻止同时修改被两个以上处理器缓存的内存区域数据。一个处理器的缓存回写到内存会导致其他处理器的缓存无效。

三、指令重排序

Java语言规范规定JVM线程内部维持顺序化语义。即只要程序的最终结果与它顺序化情况的结果相等,那么指令的执行顺序可以与代码顺序不一致,此过程叫指令的重排序。指令重排序的意义:JVM能根据处理器特性(CPU多级缓存系统、多核处理器等)适当的对机器指令进行重排序,使机器指令能更符合CPU的执行特性,最大限度的发挥机器性能。在编译器与CPU处理器中都能执行指令重排优化操作。

volatile保证可见性及重排序方法

JMM内存屏障插入策略:

  • 在每个volatile写操作的前面插入一个StoreStore屏障
  • 在每个volatile写操作的后面插入一个StoreLoad屏障
  • 在每个volatile读操作的后面插入一个LoadLoad屏障
  • 在每个volatile读操作的后面插入一个LoadStore屏障

不同硬件实现内存屏障的方式不同,Java内存模型屏蔽了这种底层硬件平台的差异,由JVM来为不同的平台生成相应的机器码。

以上就是volatile保证可见性及重排序方法的详细内容,更多关于volatile可见性重排序的资料请关注三水点靠木其它相关文章!

Java/Android 相关文章推荐
Java 中的 Unsafe 魔法类的作用大全
Jun 26 Java/Android
java实现对Hadoop的操作
Jul 01 Java/Android
JavaGUI模仿QQ聊天功能完整版
Jul 04 Java/Android
Java SSM配置文件案例详解
Aug 30 Java/Android
Java Lambda表达式常用的函数式接口
Apr 07 Java/Android
Spring Data JPA框架Repository自定义实现
Apr 28 Java/Android
Java中生成微信小程序太阳码的实现方案
Jun 01 Java/Android
Android 中的类文件和类加载器详情
Jun 05 Java/Android
Java实现简单小画板
Jun 10 Java/Android
springboot集成redis存对象乱码的问题及解决
Jun 16 Java/Android
Java实现HTML转为Word的示例代码
Jun 28 Java/Android
Spring Boot 的创建和运行示例代码详解
Jul 23 Java/Android
app场景下uniapp的扫码记录
Jul 23 #Java/Android
IDEA中sout快捷键无效问题的解决方法
Jul 23 #Java/Android
Spring Boot 的创建和运行示例代码详解
阿里面试Nacos配置中心交互模型是push还是pull原理解析
Jul 23 #Java/Android
java实现web实时消息推送的七种方案
前端与RabbitMQ实时消息推送未读消息小红点实现示例
springboot+rabbitmq实现智能家居实例详解
You might like
php设计模式 Builder(建造者模式)
2011/06/26 PHP
php使用pdo连接报错Connection failed SQLSTATE的解决方法
2014/12/15 PHP
WordPress的文章自动添加关键词及关键词的SEO优化
2016/03/01 PHP
JQuery 常用方法和事件详细介绍
2013/04/18 Javascript
jquery的ajax异步请求接收返回json数据实例
2014/06/16 Javascript
JS实现点击颜色块切换指定区域背景颜色的方法
2015/02/25 Javascript
jQuery实现的点赞随机数字显示动画效果(附在线演示与demo源码下载)
2015/12/31 Javascript
学习使用jquery iScroll.js移动端滚动条插件
2020/03/24 Javascript
关于javascript事件响应的基础语法总结(必看篇)
2016/12/26 Javascript
JS+DIV实现的卷帘效果示例
2017/03/22 Javascript
ES6新特性五:Set与Map的数据结构实例分析
2017/04/21 Javascript
在一个页面实现两个zTree联动的方法
2017/12/20 Javascript
js 图片转base64的方式(两种)
2018/04/24 Javascript
js限制input只能输入有效的数字(第一个不能是小数点)
2018/09/28 Javascript
详解vue服务端渲染浏览器端缓存(keep-alive)
2018/10/12 Javascript
JavaScript实现随机五位数验证码
2019/09/27 Javascript
如何编写一个 Webpack Loader的实现
2020/10/18 Javascript
[27:28]Ti4 冒泡赛第二天 iG vs NEWBEE 1
2014/07/15 DOTA
python下paramiko模块实现ssh连接登录Linux服务器
2015/06/03 Python
python动态加载包的方法小结
2016/04/18 Python
python中将函数赋值给变量时需要注意的一些问题
2017/08/18 Python
Python Numpy:找到list中的np.nan值方法
2018/10/30 Python
python关于调用函数外的变量实例
2019/12/26 Python
Python魔法方法 容器部方法详解
2020/01/02 Python
openCV提取图像中的矩形区域
2020/07/21 Python
Python实现树莓派摄像头持续录像并传送到主机的步骤
2020/11/30 Python
EQVVS官网:设计师男装和女装
2018/10/24 全球购物
Currentbody法国:健康与美容高科技产品
2020/08/16 全球购物
美国乒乓球设备、配件和服装品牌:Killerspin
2020/06/07 全球购物
学生实习介绍信
2014/01/15 职场文书
假面舞会策划方案
2014/05/29 职场文书
意外伤害赔偿协议书
2014/09/16 职场文书
计划生育证明格式及范本
2014/10/09 职场文书
学院党的群众路线教育实践活动第一阶段情况汇报
2014/10/25 职场文书
退货证明模板
2015/06/23 职场文书
导游词之镜泊湖
2019/12/09 职场文书