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 相关文章推荐
SpringAop日志找不到方法的处理
Jun 21 Java/Android
使用feign服务调用添加Header参数
Jun 23 Java/Android
分析Java中Map的遍历性能问题
Jun 26 Java/Android
Spring mvc是如何实现与数据库的前后端的连接操作的?
Jun 30 Java/Android
spring cloud gateway中如何读取请求参数
Jul 15 Java/Android
SpringBoot+VUE实现数据表格的实战
Aug 02 Java/Android
在Spring-Boot中如何使用@Value注解注入集合类
Aug 02 Java/Android
RestTemplate如何通过HTTP Basic Auth认证示例说明
Mar 17 Java/Android
JAVA长虹键法之建造者Builder模式实现
Apr 10 Java/Android
详解Flutter网络请求Dio库的使用及封装
Apr 14 Java/Android
JavaScript正则表达式实现注册信息校验功能
May 30 Java/Android
详解Flutter自定义应用程序内键盘的实现方法
Jun 14 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
Windows下PHP5和Apache的安装与配置
2006/09/05 PHP
dedecms 制作模板中使用的全局标记图文教程
2007/03/11 PHP
php验证码的制作思路和实现方法
2015/11/12 PHP
PHP中类的继承和用法实例分析
2016/05/24 PHP
Yii2框架制作RESTful风格的API快速入门教程
2016/11/08 PHP
php创建多级目录与级联删除文件的方法示例
2019/09/12 PHP
JS中FRAME的操作问题实例分析
2014/10/21 Javascript
Javascript实现字数统计
2015/07/03 Javascript
jQuery的end()方法使用详解
2015/07/15 Javascript
使用EVAL处理jqchart jquery 折线图返回数据无效的解决办法
2015/11/26 Javascript
详谈jQuery Ajax(load,post,get,ajax)的用法
2017/03/02 Javascript
JavaScript函数节流的两种写法
2017/04/07 Javascript
VUE使用vuex解决模块间传值问题的方法
2017/06/01 Javascript
基于jQuery实现手风琴菜单、层级菜单、置顶菜单、无缝滚动效果
2017/07/20 jQuery
vuex学习之Actions的用法详解
2017/08/29 Javascript
Vue2.0实现调用摄像头进行拍照功能 exif.js实现图片上传功能
2018/04/28 Javascript
如何更好的编写js async函数
2018/05/13 Javascript
JavaScript事件冒泡与事件捕获实例分析
2018/08/01 Javascript
react实现换肤功能的示例代码
2018/08/14 Javascript
详解如何webpack使用DllPlugin
2018/09/30 Javascript
Python中用于计算对数的log()方法
2015/05/15 Python
Python3实现定时任务的四种方式
2019/06/03 Python
python基于celery实现异步任务周期任务定时任务
2019/12/30 Python
python列表删除和多重循环退出原理详解
2020/03/26 Python
Opencv求取连通区域重心实例
2020/06/04 Python
Pycharm编辑器功能之代码折叠效果的实现代码
2020/10/15 Python
详解Python流程控制语句
2020/10/28 Python
python中turtle库的简单使用教程
2020/11/11 Python
美国排名第一的在线葡萄酒商店:Wine.com
2016/09/07 全球购物
德国购买健身器材:AsVIVA
2017/08/09 全球购物
Bibloo匈牙利:女装、男装、童装及鞋子和配饰
2019/04/14 全球购物
Zalando Lounge瑞士:时尚与生活方式购物俱乐部
2020/03/12 全球购物
师范生自荐信
2013/10/27 职场文书
法制教育演讲稿
2014/09/10 职场文书
个人查摆问题及整改措施
2014/10/16 职场文书
2015年绩效考核工作总结
2015/05/23 职场文书