volatile为什么不能保证原子性

volatile为什么不能保证原子性首先要了解的是,volatile可以保证可见性和顺序性,这些都很好理解,那么它为什么不能保证原子性呢?可见性可见性与Java的内存模型有关,模型采用缓存与主存的方式对变量进行操作,也就是说,每个线程都有自己的缓存空间,对变量的操作都是在缓存中进行的,之后再将修改后的值返回到主存中,这就带来了问题,有可能一个线程在将共享变量修改后,还没有来的及将缓存中的变量返回给主存中,另外一个线程就对…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

首先要了解的是,volatile可以保证可见性和顺序性,这些都很好理解,那么它为什么不能保证原子性呢?

可见性

可见性与Java的内存模型有关,模型采用缓存与主存的方式对变量进行操作,也就是说,每个线程都有自己的缓存空间,对变量的操作都是在缓存中进行的,之后再将修改后的值返回到主存中,这就带来了问题,有可能一个线程在将共享变量修改后,还没有来的及将缓存中的变量返回给主存中,另外一个线程就对共享变量进行修改,那么这个线程拿到的值是主存中未被修改的值,这就是可见性的问题。

volatile很好的保证了变量的可见性,变量经过volatile修饰后,对此变量进行写操作时,汇编指令中会有一个LOCK前缀指令,这个不需要过多了解,但是加了这个指令后,会引发两件事情:

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

什么意思呢?意思就是说当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值,这就保证了可见性。

原子性

问题来了,既然它可以保证修改的值立即能更新到主存,其他线程也会捕捉到被修改后的值,那么为什么不能保证原子性呢?
首先需要了解的是,Java中只有对基本类型变量的赋值和读取是原子操作,如i = 1的赋值操作,但是像j = i或者i++这样的操作都不是原子操作,因为他们都进行了多次原子操作,比如先读取i的值,再将i的值赋值给j,两个原子操作加起来就不是原子操作了。

所以,如果一个变量被volatile修饰了,那么肯定可以保证每次读取这个变量值的时候得到的值是最新的,但是一旦需要对变量进行自增这样的非原子操作,就不会保证这个变量的原子性了。

举个栗子

一个变量i被volatile修饰,两个线程想对这个变量修改,都对其进行自增操作也就是i++,i++的过程可以分为三步,首先获取i的值,其次对i的值进行加1,最后将得到的新值写会到缓存中。
线程A首先得到了i的初始值100,但是还没来得及修改,就阻塞了,这时线程B开始了,它也得到了i的值,由于i的值未被修改,即使是被volatile修饰,主存的变量还没变化,那么线程B得到的值也是100,之后对其进行加1操作,得到101后,将新值写入到缓存中,再刷入主存中。根据可见性的原则,这个主存的值可以被其他线程可见。
问题来了,线程A已经读取到了i的值为100,也就是说读取的这个原子操作已经结束了,所以这个可见性来的有点晚,线程A阻塞结束后,继续将100这个值加1,得到101,再将值写到缓存,最后刷入主存,所以即便是volatile具有可见性,也不能保证对它修饰的变量具有原子性。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/157650.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • laravel 5.4 导出excel表格

    laravel 5.4 导出excel表格

    2021年10月24日
    43
  • 舵机控制原理详解「建议收藏」

    舵机控制原理详解「建议收藏」控制信号由接收机的通道进入信号调制芯片,获得直流偏置电压。它内部有一个基准电路,产生周期为20ms,宽度为1.5ms的基准信号,将获得的直流偏置电压与电位器的电压比较,获得电压差输出。最后,电压差的正负输出到电机驱动芯片决定电机的正反转。当电机转速一定时,通过级联减速齿轮带动电位器旋转,使得电压差为0,电机停止转动。舵机的控制一般需要一个20ms左右的时基脉冲,该脉冲的高电平部

    2022年6月15日
    37
  • idea2022 2.5激活码获取【最新永久激活】

    (idea2022 2.5激活码获取)好多小伙伴总是说激活码老是失效,太麻烦,关注/收藏全栈君太难教程,2021永久激活的方法等着你。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html1M2OME2TZY-eyJsaWNlbnNlSW…

    2022年3月13日
    782
  • activate-power-mode 写代码的时候体验狂拽酷炫的效果 (IntelliJ IDEA版安装过程及问题)「建议收藏」

    activate-power-mode 写代码的时候体验狂拽酷炫的效果 (IntelliJ IDEA版安装过程及问题)「建议收藏」初遇activate-power-mode前一段时间在微信上看到朋友发的这个插件,就收藏了,一直没试试,今天兴致一来突然想起来这么一出,就试试这是微信原文:写个HelloWord而已,要不要这么震撼?!atom上的一个插件,可以让你写代码的时候体验狂拽酷炫的效果这货全名叫activate-power-modeatompackage最新版0.3.2

    2022年7月14日
    27
  • linux export命令找不到_docker执行容器内的shell

    linux export命令找不到_docker执行容器内的shellLinuxexport命令用于设置或显示环境变量。在shell中执行程序时,shell会提供一组环境变量。export可新增,修改或删除环境变量,供后续执行的程序使用。export的效力仅及于该次登陆操作。语法export[-fnp][变量名称]=[变量设置值]参数说明:-f 代表[变量名称]中为函数名称。 -n 删除指定的变量。变量实际上并未删除,只是不会输出到后…

    2022年9月7日
    0
  • android官方原生主题,原生Android可以更换系统主题吗?

    android官方原生主题,原生Android可以更换系统主题吗?现在越来越多的智能手机用户喜欢使用原生的Android系统,因为原生Android系统更加纯净流畅,没有乱七八糟的第三方厂商软件预装,安全性更高,最重要的是原生Android可以最快获得系统更新。也有人喜欢用第三方定制的安卓系统,是因为它的可玩性更高,而其中可更换主题的功能更是受一众玩家欢迎。不过对于原生Android系统的用户来说,想要平时随随便便更换主题可不是件容易的事。原生Android用户…

    2022年6月19日
    46

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号