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框架入门之简单介绍SpringBoot框架
Jun 18 Java/Android
Java多条件判断场景中规则执行器的设计
Jun 26 Java/Android
分析Java中Map的遍历性能问题
Jun 26 Java/Android
Spring整合Mybatis的全过程
Jun 28 Java/Android
jackson json序列化实现首字母大写,第二个字母需小写
Jun 29 Java/Android
分析并发编程之LongAdder原理
Jun 29 Java/Android
Springboot如何同时装配两个相同类型数据库
Nov 17 Java/Android
Java使用JMeter进行高并发测试
Nov 23 Java/Android
java协程框架quasar和kotlin中的协程对比分析
Feb 24 Java/Android
使用Java去实现超市会员管理系统
Mar 18 Java/Android
Android开发实现极为简单的QQ登录页面
Apr 24 Java/Android
Android开发之底部导航栏的快速实现
Apr 28 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读取富文本的时p标签会出现红线是怎么回事
2014/05/13 PHP
基于CakePHP实现的简单博客系统实例
2015/06/28 PHP
php验证码生成代码
2015/11/11 PHP
laravel Task Scheduling(任务调度)在windows下的使用详解
2019/10/22 PHP
获取页面高度,窗口高度,滚动条高度等参数值getPageSize,getPageScroll
2006/09/22 Javascript
firefox中用javascript实现鼠标位置的定位
2007/06/17 Javascript
基于jquery的图片懒加载js
2010/06/30 Javascript
将HTMLCollection/NodeList/伪数组转换成数组的实现方法
2011/06/20 Javascript
JavaScript高级程序设计(第3版)学习笔记12 js正则表达式
2012/10/11 Javascript
用JQuery 判断某个属性是否存在hasAttr的解决方法
2013/04/26 Javascript
javascript:FF/Chrome与IE动态加载元素的区别说明
2014/01/26 Javascript
js比较日期大小的方法
2015/05/12 Javascript
jQuery动态星级评分效果实现方法
2015/08/06 Javascript
jquery实现倒计时功能
2015/12/28 Javascript
vue-cli如何快速构建vue项目
2017/04/26 Javascript
微信小程序实现漂亮的弹窗效果
2020/05/26 Javascript
jQuery选择器选中最后一个元素,倒数第二个元素操作示例
2018/12/10 jQuery
JavaScript常见事件处理程序实例总结
2019/01/05 Javascript
layui对工具条进行选择性的显示方法
2019/09/19 Javascript
Vue SPA 首屏优化方案
2021/02/26 Vue.js
Python简单实现enum功能的方法
2016/04/25 Python
Python脚本获取操作系统版本信息
2016/12/17 Python
Python爬虫实例_利用百度地图API批量获取城市所有的POI点
2018/01/10 Python
Flask和Django框架中自定义模型类的表名、父类相关问题分析
2018/07/19 Python
PySide和PyQt加载ui文件的两种方法
2019/02/27 Python
python版百度语音识别功能
2019/07/09 Python
pycharm实现在子类中添加一个父类没有的属性
2020/03/12 Python
python中not、and和or的优先级与详细用法介绍
2020/11/03 Python
python3 os进行嵌套操作的实例讲解
2020/11/19 Python
Python实现Appium端口检测与释放的实现
2020/12/31 Python
详解webapp页面滚动卡顿的解决办法
2018/12/26 HTML / CSS
UGG英国官方网站:UGG UK
2018/02/08 全球购物
暑假社会实践证明格式
2014/10/28 职场文书
业务员岗位职责范本
2015/04/03 职场文书
整脏治乱工作简报
2015/07/21 职场文书
TS 类型收窄教程示例详解
2022/09/23 Javascript