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 相关文章推荐
手把手教你用SpringBoot将文件打包成zip存放或导出
Jun 11 Java/Android
Java方法重载和方法重写的区别到底在哪?
Jun 11 Java/Android
Springboot使用Spring Data JPA实现数据库操作
Jun 30 Java/Android
Java使用jmeter进行压力测试
Jul 09 Java/Android
java如何实现socket连接方法封装
Sep 25 Java/Android
Java tomcat手动配置servlet详解
Nov 27 Java/Android
maven依赖的version声明控制方式
Jan 18 Java/Android
Android Flutter实现图片滑动切换效果
Apr 07 Java/Android
Java8利用Stream对列表进行去除重复的方法详解
Apr 14 Java/Android
Java 多态分析
Apr 26 Java/Android
Spring 使用注解开发
May 20 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 将bmp图片转为jpg等其他任意格式的图片
2009/06/29 PHP
从性能方面考虑PHP下载远程文件的3种方法
2015/12/29 PHP
tp5框架使用cookie加密算法实现登录功能示例
2020/02/10 PHP
JS 容错处理代码, 屏蔽错误信息
2021/03/09 Javascript
setTimeout与setInterval在不同浏览器下的差异
2010/01/24 Javascript
js实现的仿新浪微博完美的时间组件升级版
2011/12/20 Javascript
js动态控制table的tr、td增加及删除的具体实现
2014/04/30 Javascript
深入理解JavaScript系列(48):对象创建模式(下篇)
2015/03/04 Javascript
JavaScript实现鼠标滑过处生成气泡的方法
2015/05/16 Javascript
jQuery判断指定id的对象是否存在的方法
2015/05/22 Javascript
jQuery.form插件的使用及跨域异步上传文件
2016/04/27 Javascript
js只执行1次的函数示例
2016/07/20 Javascript
jQuery实现磁力图片跟随效果完整示例
2016/09/16 Javascript
一篇看懂vuejs的状态管理神器 vuex状态管理模式
2017/04/20 Javascript
vue给input file绑定函数获取当前上传的对象完美实现方法
2017/12/15 Javascript
如何开发出更好的JavaScript模块
2017/12/22 Javascript
angular第三方包开发整理(小结)
2018/04/19 Javascript
Angular 实现输入框中显示文章标签的实例代码
2018/11/07 Javascript
小程序hover-class点击态效果实现
2019/02/26 Javascript
Easyui 去除jquery-easui tab页div自带滚动条的方法
2019/05/10 jQuery
详解基于mpvue微信小程序下载远程图片到本地解决思路
2019/05/16 Javascript
Vue项目页面跳转时浏览器窗口上方显示进度条功能
2020/03/26 Javascript
详解Vue串联过滤器的使用场景
2020/04/30 Javascript
在Uni中使用Vue的EventBus总线机制操作
2020/07/31 Javascript
vue自定义树状结构图的实现方法
2020/10/18 Javascript
Python多线程实例教程
2014/09/06 Python
Python的Django框架下管理站点的基本方法
2015/07/17 Python
浅谈django rest jwt vue 跨域问题
2018/10/26 Python
Python中logging实例讲解
2019/01/17 Python
python读取图片任意范围区域
2019/01/23 Python
对django views中 request, response的常用操作详解
2019/07/17 Python
Python学习之路安装pycharm的教程详解
2020/06/17 Python
党员个人自我剖析材料
2014/10/08 职场文书
校园学雷锋广播稿
2014/10/08 职场文书
导游词之苏州阳澄湖
2019/11/15 职场文书
Nginx的基本概念和原理
2022/03/21 Servers