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

JavaEE之volatile关键字

一.内存可见性问题

什么是内存可见性问题

计算机运行的程序/代码,往往需要访问数据。这些数据往往存在于内存中。

cup使用此变量时,就会把内存中的数据先读出来,加载到cpu寄存器中,再去参与运算。

但是,关键是cpu读取内存的速度非常慢。这是相对的,读内存比读取硬盘快成千上万倍,而读取寄存器又比读取内存快了成千上万倍。而这里,cpu计算时,就是涉及到读取内存和读取寄存器的操作。

读取寄存器非常快,一旦涉及到读内存,cpu就慢下来了。为例提高效率,操作系统就可能在代码逻辑不变的情况下对代码进行优化,把本来读取内存的操作优化成读取寄存器的操作,减少了读取内存的次数,也就提高了效率。但是此时,如果有另一个线程对该数进行了修改并放到内存中,前一个线程就感知不到变化,就会出现问题。这就出现了内存可见性问题,也是线程安全问题的成因之一,明明内存已经修改了值,它却视而不见

例如下面的情况:

明明修改了isQuit的值,但线程1还在循环,说明while中读取到的值还是0,说明没有看到内存的修改,这就是内存可见性问题,是由于多线程引起的。我们来解释一下:

while(isQuit==0)这个判断分为俩步:第一步,load,就是cpu读取内存,将内存中isQuit的值记录到寄存器中;第二步,读取寄存器,判断isQuit的值是否为0(cmp)。

由于只是一个循环,短时间内就会进行大量循环,也就是会进行大量load,cmp操作。但是,此时JVM发现,load一次的时间内,就可以cmp成千上万次,而且发现前几次时,每次load和cmp的结果都是一样的,并且load有费时,所以编译器就做了大胆决定:不再进行load内存,而是直接从寄存器中取出isQuit。

编译器的优化:初心是好的,想要提高工作效率,但没想到其他线程动了手脚,而编译器却察觉不到,所以就做出了错误决定。

其实从上述分析中,我们可以大胆猜测,要是循环慢一点,就可能不会进行优化了,如下:

虽然只休眠了50毫秒,但却正常了,所以编译器到底什么时候触发优化机制,我们无法确定。

关于内存可见性,还涉及到一个JMM(Java Memory Model)Java内存模型这个概念。它时说到了主内存和工作内存,主内存就是我们常说的内存,而寄存器,缓存等统称为工作内存。

如何解决内存可见性问题

上述问题如何解决?我们怎么告诉编译器不要进行优化?

这就引出了volatile关键字

二.volatile关键字

volatile关键字修饰的变量能够保证内存可见性

它是如何保证被修饰的变量时内存可见性的呢?分两方面:一方面,代码在写入或修改ivolatile修饰的变量时,会先改写工作内存中的变量的值,然后会将改后的值从工作内存中刷新到主内存中;另一方面,在读取该变量时,会先将变量从主内存加载到寄存器中,再从寄存器中读取。

也就是说,加上volatile后,会让系统强制读写内存,而不是直接读写寄存器,虽然速度慢了,但时却保证了准确性。

volatile不能保证原子性

他只能让读取内存操作不被优化成读寄存器,而不能将代码捆绑到一起。保证原子性的操作还得是用synchronized

http://www.lryc.cn/news/313330.html

相关文章:

  • 代码学习记录10
  • java——2024-03-03
  • Ubuntu安装conda以后,给jupyter安装C++内核
  • 【谈判】核心思想(抓大放小)
  • 洛谷P5908 猫猫和企鹅 做题反思(2024.3.7)
  • 常见的验证码
  • 11. C语言标准函数库
  • 2016年认证杯SPSSPRO杯数学建模C题(第一阶段)如何有效的抑制校园霸凌事件的发生解题全过程文档及程序
  • 设计模式-抽象工厂模式实践案例
  • 用readproc函数读取进程的状态
  • 在高并发、高性能、高可用 三高项目中如何设计适合实际业务场景的分布式id(一)
  • redis最新版本在Windows系统上的安装
  • 【深度优先】【图论】【C++算法】2045. 到达目的地的第二短时间
  • 思维题(蓝桥杯 填空题 C++)
  • Meta的Llama2模型已上线!但我为何更推荐你从HuggingFace获取?还有Code Llama等你来解锁!
  • CAN总线及通讯的工作原理
  • linux下修改网卡MAC地址
  • 47、WEB攻防——通用漏洞Java反序列化EXP生成数据提取组件安全
  • phpstorm console xdebug
  • Vue template到render过程
  • 【你也能从零基础学会网站开发】Web建站之HTML+CSS入门篇 CSS常用属性
  • Golang 写日志到文件
  • 数字孪生10个技术栈:数据处理的六步骤,以获得可靠数据。
  • 运维随录实战(5)之centos搭建jenkins
  • css clip-path polygon属性实现直角梯形
  • Manz高压清洗机S11-028GCH-High Quality Cleaner 操作使用说明492页
  • 图像处理与视觉感知---期末复习重点(2)
  • 【机器学习】三要素——数据、模型、算法
  • Spring框架Bean对象的五个作用域
  • IoT数据采集网关在企业应用中扮演着关键角色-天拓四方