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在个人电脑上实现微信扫码支付
Jun 13 Java/Android
java设计模式--三种工厂模式详解
Jul 21 Java/Android
mybatis中注解与xml配置的对应关系和对比分析
Aug 04 Java/Android
Java获取e.printStackTrace()打印的信息方式
Aug 07 Java/Android
深入浅出讲解Java8函数式编程
Jan 18 Java/Android
Java实现给Word文件添加文字水印
Feb 15 Java/Android
Spring this调用当前类方法无法拦截的示例代码
Mar 20 Java/Android
Java8 CompletableFuture 异步回调
Apr 28 Java/Android
Android中View.post和Handler.post的关系
Jun 05 Java/Android
ConditionalOnProperty配置swagger不生效问题及解决
Jun 14 Java/Android
SpringBoot详解自定义Stater的应用
Jul 15 Java/Android
spring 项目实现限流方法示例
Jul 15 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
ThinkPHP使用PHPExcel实现Excel数据导入导出完整实例
2014/07/22 PHP
PHP基于简单递归函数求一个数阶乘的方法示例
2017/04/26 PHP
PHP实现获取ip地址的5种方法,以及插入用户登录日志操作示例
2019/02/28 PHP
PHP开发实现快递查询功能详解
2019/04/08 PHP
用Javascript读取中文COOKIE的解决办法
2007/02/15 Javascript
从面试题学习Javascript 面向对象(创建对象)
2012/03/30 Javascript
Android中资源文件(非代码部分)的使用概览
2012/12/18 Javascript
jquery prop的使用介绍及与attr的区别
2013/12/19 Javascript
利用JS判断用户是否上网(连接网络)
2013/12/23 Javascript
优化Node.js Web应用运行速度的10个技巧
2014/09/03 Javascript
js显示动态时间的方法详解
2016/08/20 Javascript
分分钟玩转Vue.js组件(二)
2017/03/01 Javascript
JS交互点击WKWebView中的图片实现预览效果
2018/01/05 Javascript
vue中实现在外部调用methods的方法(推荐)
2018/02/08 Javascript
JS实现求5的阶乘示例
2019/01/21 Javascript
VSCode写vue项目一键生成.vue模版,修改定义其他模板的方法
2020/04/17 Javascript
vue中keep-alive、activated的探讨和使用详解
2020/07/26 Javascript
vue 实现element-ui中的加载中状态
2020/11/11 Javascript
[02:35]DOTA2英雄基础教程 狙击手
2014/01/14 DOTA
[02:33]2018DOTA2亚洲邀请赛赛前采访——LGD
2018/04/04 DOTA
Python 字符串操作方法大全
2014/03/11 Python
用Python编写简单的定时器的方法
2015/05/02 Python
python实现百度语音识别api
2018/04/10 Python
python使用matplotlib模块绘制多条折线图、散点图
2020/04/26 Python
python requests使用socks5的例子
2019/07/25 Python
python模块常用用法实例详解
2019/10/17 Python
python和C++共享内存传输图像的示例
2020/10/27 Python
HTML5中的新元素介绍
2008/10/17 HTML / CSS
美国一家专业的太阳镜网上零售商:Solstice太阳镜
2016/07/25 全球购物
成人高等教育毕业生自我鉴定
2013/10/22 职场文书
大学生简短的自我评价分享
2014/02/20 职场文书
车辆转让协议书
2014/04/15 职场文书
政府信息公开实施方案
2014/05/09 职场文书
简单通用的简历自我评价
2014/09/21 职场文书
开展党的群众路线教育实践活动领导班子对照检查材料
2014/09/25 职场文书
以下牛机,你有几个
2022/04/05 无线电