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
mybatis中sql语句CDATA标签的用法说明
Jun 30 Java/Android
Java中多线程下载图片并压缩能提高效率吗
Jul 01 Java/Android
SpringMVC 整合SSM框架详解
Aug 30 Java/Android
Java实现学生管理系统(IO版)
Feb 24 Java/Android
springboot+zookeeper实现分布式锁
Mar 21 Java/Android
spring注解 @PropertySource配置数据源全流程
Mar 25 Java/Android
Java设计模式之代理模式
Apr 22 Java/Android
Java设计模式中的命令模式
Apr 28 Java/Android
Java时间工具类Date的常用处理方法
May 25 Java/Android
springboot集成redis存对象乱码的问题及解决
Jun 16 Java/Android
MyBatis在注解上使用动态SQL方式(@select使用if)
Jul 07 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并发对MYSQL造成压力的解决方法
2013/02/21 PHP
php Hex RGB颜色值互换的使用
2013/05/10 PHP
IIS6.0中配置php服务全过程解析
2013/08/07 PHP
Yii实现单用户博客系统文章详情页插入评论表单的方法
2015/12/28 PHP
基于PHP实现通过照片获取ip地址
2016/04/26 PHP
PHP文件管理之实现网盘及压缩包的功能操作
2017/09/20 PHP
picChange 图片切换特效的函数代码
2010/05/06 Javascript
jquery 倒计时效果实现秒杀思路
2013/09/11 Javascript
window.onresize 多次触发的解决方法
2013/11/08 Javascript
利用a标签自动解析URL分析网址实例
2014/10/20 Javascript
js实现文字在按钮上滚动的方法
2015/08/20 Javascript
JS导出PDF插件的方法(支持中文、图片使用路径)
2016/07/12 Javascript
各式各样的导航条效果css3结合jquery代码实现
2016/09/17 Javascript
js通过classname来获取元素的方法
2016/11/24 Javascript
JS中对数组元素进行增删改移的方法总结
2016/12/15 Javascript
详解Vue爬坑之vuex初识
2017/06/14 Javascript
vue-cli3配置favicon.ico和title的流程
2020/10/27 Javascript
react-native 实现购物车滑动删除效果的示例代码
2021/01/15 Javascript
[01:15:00]LGD vs Mineski Supermajor 胜者组 BO3 第一场 6.5
2018/06/06 DOTA
使用Python压缩和解压缩zip文件的教程
2015/05/06 Python
Python判断值是否在list或set中的性能对比分析
2016/04/16 Python
Python变量和字符串详解
2017/04/29 Python
Python元组拆包和具名元组解析实例详解
2018/03/26 Python
python time.sleep()是睡眠线程还是进程
2019/07/09 Python
Django 源码WSGI剖析过程详解
2019/08/05 Python
tensorflow 实现自定义layer并添加到计算图中
2020/02/04 Python
python ffmpeg任意提取视频帧的方法
2020/02/21 Python
使用python实现微信小程序自动签到功能
2020/04/27 Python
Windows下Sqlmap环境安装教程详解
2020/08/04 Python
金融行业职业生涯规划范文
2014/01/17 职场文书
先进工作者申报材料
2014/12/23 职场文书
4S店客服专员岗位职责
2015/04/07 职场文书
2015年信息化建设工作总结
2015/07/23 职场文书
婚庆答谢词大全
2015/09/29 职场文书
2016年12月份红领巾广播稿
2015/12/21 职场文书
GPU服务器的多用户配置方法
2022/07/07 Servers