当前位置: 首页 > news >正文

【< volatile 关键字专题>】

volatile 关键字专题

          • [1] 谈一下你对 volatile 关键字的理解?
          • [2]Volatile如何保证可见性和有序性?
            • 1. 可见性
            • 2.有序性的
          • [3] volatile在什么情况下可以替代锁?

[1] 谈一下你对 volatile 关键字的理解?

**答:**volatile 关键字是用来保证有序性和可见性的。

  1. 保证了不同线程对该变量操作的内存可见性;
  2. 禁止指令重排序。

我们所写的代码,不一定是按照我们自己书写的顺序来执行的,编译器会做重排序,CPU 也会做重排序的,这样做是为了减少流水线阻塞,提高 CPU 的执行效率。这就需要有一定的顺序和规则来保证,不然程序员自己写的代码都不知道对不对了,所以有 happens-before 规则,其中有条就是 volatile 变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作、有序性实现的是通过插入内存屏障来保证的。

解析:

  • volatile 可以保证主内存和工作内存直接产生交互,进行读写操作,保证可见性
  • volatile 仅能保证变量写操作的原子性,不能保证读写操作的原子性。
  • volatile可以禁止指令重排序(通过插入内存屏障),典型案例是在单例模式中使用。

volatile变量的开销:

volatile不会导致线程上下文切换,但是其读取变量的成本较高,因为其每次都需要从高速缓存或者主内存中读取,无法直接从寄存器中读取变量。

[2]Volatile如何保证可见性和有序性?

https://blog.csdn.net/duzhe2905/article/details/106038681?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.compare&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.compare

https://blog.csdn.net/qq_35590091/article/details/106986536

image-20200518151004751
1. 可见性

主内存与工作内存

java内存模型规定了所有的变量都存储在主内存。每条线程还有自己的工作内存,线程的工作内存中保存了被改线程使用到的变量的主内存副本拷贝。线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存中的变量。不同线程之间也无法直接访问对方工作内存中的变量,线程间变量传递均需要通过主内存来完成。当多个线程操作的变量涉及到同一个主内存区域,将可能导致各自的工作线程数据不一致,这样就导致变量同步回主内存的时候可能冲突导致数据丢失。
原文链接:https://blog.csdn.net/y124675160/article/details/78310121

在这里插å¥å›¾ç‰‡æè¿°

volatile修饰的共享变量进行写操作的时候多出一条带lock前缀的指令,lock前缀的指令在多核处理器下会引发两件事情

  1. 将当前处理器缓存行的数据写回到系统内存。
  2. 这个写回内存的操作会使在其他CPU里缓存了该内存地址的数据无效。

为了提高处理速度,处理器不直接和内存进行通信,而是先将系统内存的数据读到内部缓存后再进行操作,但是操作完了不知道什么时候写回内存。而对声明了volatile关键字的变量进行写操作,JVM会向处理器发送一条lock前缀的指令,将这个变量所在的缓存行立即写回系统内存。并且为了保证各个处理器的缓存是一致的,实现了缓存一致性协议,各个处理通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,那么下次对这个数据进行操作,就会重新从系统内存中获取最新的值。对应JMM来说就是:

  1. Lock前缀的指令让线程工作内存中的值写回主内存中;
  2. 通过缓存一致性协议,其他线程如果工作内存中存了该共享变量的值,就会失效;
  3. 其他线程会重新从主内存中获取最新的值;

原文链接:https://blog.csdn.net/y124675160/article/details/78310121

2.有序性的

为了性能优化,JVM会在不改变数据依赖性的情况下,允许编译器和处理器对指令序列进行重排序,而有序性问题指的就是程序代码执行的顺序与程序员编写程序的顺序不一致,导致程序结果不正确的问题。而加了volatile修饰的共享变量,则通过内存屏障解决了多线程下有序性问题。

内次屏障分为以下4类:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qZiQWZ1C-1596597309344)(X:\Users\xu\AppData\Roaming\Typora\typora-user-images\image-20200723232539965.png)]
为了实现volatile的内存语义,编译器在生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序,下面是基于保守策略的JMM内存平展插入策略。

  • 在每个volatile写操作的前面插入一个StoreStore屏障,可以保证前面普通的写操作已经对任意处理器可见。
  • 在每个volatile写操作的后面插入一个StoreLoad屏障,可以保证前面普通的写操作已经对任意处理器可见。
  • 在每个volatile读操作的后面插入一个LoadLoad屏障,确保前面的数据先于后面的指令写入工作内存。
  • 在每个volatile读操作的后面插入一个LoadStore屏障,确保前面的数据先于后面的指令写入工作内存。

volatile在写操作前后插入了内存屏障后生成的指令序列,示意图如下:

在这里插å
¥å›¾ç‰‡æè¿°

volatile在读操作后面插入了内存屏障后生成的指令序列示意图如下:

在这里插å
¥å›¾ç‰‡æè¿°

[3] volatile在什么情况下可以替代锁?

volatile是一个轻量级的锁,适合多个线程共享一个状态变量,锁适合多个线程共享一组状态变量。可以将多个线程共享的一组状态变量合并成一个对象,用一个volatile变量来引用该对象,从而替代锁。

理解volatile和CAS配合使用原理

https://blog.csdn.net/liaoxiaolin520/article/details/93711623

相关文章:

  • 【< synchronized专题>】
  • jQuery 之 $(this) 出了什么问题?
  • 【< AQS>】
  • 软件抄袭与创新的思考
  • 【< J.U.C>】
  • Github实例教程-创建库、创建主页
  • 【<Java中的线程池>】
  • 关于数组添加值和访问值的一些小问题
  • hdu 5623 KK's Number(dp)
  • 【阅读源码系列】HashMap源码分析(JDK1.7和JDK1.8)
  • 使用开源的PullToRefreshScrollView scrollTo和scrollby遇到的问题
  • 【阅读源码系列】ThreadPoolExecutor源码
  • ​猴子吃桃问题:每天都吃了前一天剩下的一半多一个。
  • YII 路由配置
  • 讲一下ISO七层模型?
  • input的行数自动增减
  • JavaScript创建对象的四种方式
  • JavaScript的使用你知道几种?(上)
  • JavaScript设计模式系列一:工厂模式
  • java中的hashCode
  • jdbc就是这么简单
  • ng6--错误信息小结(持续更新)
  • PaddlePaddle-GitHub的正确打开姿势
  • 关于Flux,Vuex,Redux的思考
  • 解决jsp引用其他项目时出现的 cannot be resolved to a type错误
  • 深入浏览器事件循环的本质
  • 适配mpvue平台的的微信小程序日历组件mpvue-calendar
  • 我建了一个叫Hello World的项目
  • 详解NodeJs流之一
  • 由插件封装引出的一丢丢思考
  • MyCAT水平分库
  • 完善智慧办公建设,小熊U租获京东数千万元A+轮融资 ...
  • 正则表达式-基础知识Review
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • (01)ORB-SLAM2源码无死角解析-(66) BA优化(g2o)→闭环线程:Optimizer::GlobalBundleAdjustemnt→全局优化
  • (a /b)*c的值
  • (poj1.2.1)1970(筛选法模拟)
  • (pojstep1.1.2)2654(直叙式模拟)
  • (补)B+树一些思想
  • (附源码)计算机毕业设计ssm本地美食推荐平台
  • (机器学习-深度学习快速入门)第三章机器学习-第二节:机器学习模型之线性回归
  • (十八)devops持续集成开发——使用docker安装部署jenkins流水线服务
  • (原)本想说脏话,奈何已放下
  • (转)eclipse内存溢出设置 -Xms212m -Xmx804m -XX:PermSize=250M -XX:MaxPermSize=356m
  • (转)利用PHP的debug_backtrace函数,实现PHP文件权限管理、动态加载 【反射】...
  • *setTimeout实现text输入在用户停顿时才调用事件!*
  • .net core 调用c dll_用C++生成一个简单的DLL文件VS2008
  • .net core控制台应用程序初识
  • .net 前台table如何加一列下拉框_如何用Word编辑参考文献
  • .NET/ASP.NETMVC 大型站点架构设计—迁移Model元数据设置项(自定义元数据提供程序)...
  • .NET中的Exception处理(C#)
  • @configuration注解_2w字长文给你讲透了配置类为什么要添加 @Configuration注解
  • @ModelAttribute 注解
  • [ vulhub漏洞复现篇 ] JBOSS AS 5.x/6.x反序列化远程代码执行漏洞CVE-2017-12149
  • [20160807][系统设计的三次迭代]