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 相关文章推荐
总结一下关于在Java8中使用stream流踩过的一些坑
Jun 24 Java/Android
详解Java分布式事务的 6 种解决方案
Jun 26 Java/Android
Java中使用Filter过滤器的方法
Jun 28 Java/Android
SpringBoot+VUE实现数据表格的实战
Aug 02 Java/Android
Java spring单点登录系统
Sep 04 Java/Android
Java 实战项目之家居购物商城系统详解流程
Nov 11 Java/Android
Java异常处理try catch的基本用法
Dec 06 Java/Android
JavaWeb实现显示mysql数据库数据
Mar 19 Java/Android
Java Spring Boot 正确读取配置文件中的属性的值
Apr 20 Java/Android
Qt数据库应用之实现图片转pdf
Jun 01 Java/Android
SpringBoot使用AOP实现统计全局接口访问次数详解
Jun 16 Java/Android
spring boot实现文件上传
Aug 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
php 模拟get_headers函数的代码示例
2013/04/27 PHP
PHP中使用asort进行中文排序失效的问题处理
2014/08/18 PHP
php实现读取内存顺序号
2015/03/29 PHP
java模拟PHP的pack和unpack类
2016/04/13 PHP
javascript Array.remove() 数组删除
2009/08/06 Javascript
JS中的substring和substr函数的区别说明
2013/05/07 Javascript
getAsDataURL在Firefox7.0下无法预览本地图片的解决方法
2013/11/15 Javascript
Jquery的Tabs内容轮换效果实现代码,几行搞定
2014/02/12 Javascript
超棒的响应式布局jQuery插件Freetile.js
2014/11/17 Javascript
jQuery选择器源码解读(一):Sizzle方法
2015/03/31 Javascript
angular2使用简单介绍
2016/03/01 Javascript
基于BootStrap的图片轮播效果展示实例代码
2016/05/23 Javascript
JS组件Bootstrap Table布局详解
2016/05/27 Javascript
vue实现div拖拽互换位置
2020/07/29 Javascript
vue-cli2与vue-cli3在一台电脑共存的实现方法
2019/09/25 Javascript
区分vue-router的hash和history模式
2020/10/03 Javascript
Python set集合类型操作总结
2014/11/07 Python
python实现查找两个字符串中相同字符并输出的方法
2015/07/11 Python
Python装饰器入门学习教程(九步学习)
2016/01/28 Python
Python判断某个用户对某个文件的权限
2016/10/13 Python
深入分析python数据挖掘 Json结构分析
2018/04/21 Python
python将秒数转化为时间格式的实例
2018/09/16 Python
python3 mmh3安装及使用方法
2019/10/09 Python
Python读取文件内容为字符串的方法(多种方法详解)
2020/03/04 Python
Python常见反爬虫机制解决方案
2020/06/01 Python
解决pytorch下出现multi-target not supported at的一种可能原因
2021/02/06 Python
乐天旅游香港网站:日本饭店预订
2017/11/29 全球购物
美国在线旅行社:Crystal Travel
2018/09/11 全球购物
丝绸和人造花卉、植物和树木:Nearly Natural
2018/11/28 全球购物
酒店销售经理岗位职责
2014/01/31 职场文书
环保倡议书格式范文
2014/05/14 职场文书
社保缴纳证明申请书
2014/11/03 职场文书
私用公车造成事故检讨书
2014/11/16 职场文书
有关花店创业的计划书模板
2019/08/27 职场文书
nginx的zabbix 5.0安装部署的方法步骤
2021/07/16 Servers
Ruby序列化和持久化存储 Marshal和Pstore介绍
2022/04/18 Ruby