voliate关键字的应用误区

voliate关键字的应用误区写下这篇博客也是因为本人之前对voliate关键字理解不透彻,才有了应用误区,希望同样没有理解到位的朋友可以一起踩坑,也欢迎上帝视角明明白白的大佬指出本文的不当之处。先说一下自己之前对voliate的理解,voliate通过内存屏障可以禁止指令重排序和保证可见性,但是不能保证并发安全。禁止指令重排序就不说了,主要说一说如何保证可见性以及为什么不能保证并发安全。首先理解一下一个线程如何去修改…

大家好,又见面了,我是你们的朋友全栈君。

写下这篇博客也是因为本人之前对voliate关键字理解不透彻,才有了应用误区,希望同样没有理解到位的朋友可以一起踩坑,也欢迎上帝视角明明白白的大佬指出本文的不当之处。

先说一下自己之前对voliate的理解,voliate通过内存屏障可以禁止指令重排序和保证可见性,但是不能保证并发安全。禁止指令重排序就不说了,主要说一说如何保证可见性以及为什么不能保证并发安全。

首先理解一下一个线程如何去修改变量a的值,有三步:

第一步从主内存中读取a的值到该线程的工作内存。

第二步在工作内存中修改a。

第三步将a的值刷回主内存。

被voliate修饰的变量在进行写操作时,处理器会多一条Lock指令,Lock指令会将修改后的值直接写进主内存。同时还会让其他线程的工作内存中缓存的a的值失效,这两点就可以保证了可见性,我理解的可见性是指所有线程修改a之前a的值都和主内存中一样,都是一致的。

举个栗子如果有两个thread同时操作voliate修饰变量a,thread1和thread2都将a的值从主内存中读取到工作内存中之后,thread2对a做了修改之后会使thread1工作内存中a的值失效,同时及时地将a的值刷新进主内存,这时候thread1想去修改a发现自己工作内存中的值失效了,就会去主内存中重新读取,这样就避免了典型的并发问题。日常voliate的应用场景中喜欢用来修饰全局变量,曾经以为这样就可以避免该全局变量并发问题,其实不是的。

因为voliate不能将一个非原子性的操作变为原子性。所谓原子性的操作是指该操作在执行期间不受其他操作影响。上面这个对例子中对变量a的值做修改这就不是一个原子性操作,因为这个操作有三步。

还是刚刚那个例子加深一下理解。thread1如果在第一步和第二步中间a的值被thread2修改了,这时候thread1应该在thread2修改之后的a的基础上再做修改,总之thread1的操作结果就要受其他线程影响了。重点来了!voliate可以保证thread1的操作结果正确,但是它不能阻止thread2去影响thread1的操作结果。这就是voliate不能将一个非原子性的操作变为原子性,但是加锁(该变量只能同时被一个线程操作)或者CAS无锁可以,这是题外话。

说了这么多还是没有说为什么voliate不能保证并发安全。先看个情景,还是上面这个例子,刚说thread1在第一步和第二步之间的时候thread2把a修改了,这时候voliate棒棒的一系列骚操作让thread1在执行第二步真正去修改a的时候拿到的还是最新的即thread2修改之后刷新回主内存的值。但是如果thread1在第二步和第三步之间的时候thread2把a修改了呢!这时候thread1已经把a修改完了,已经准备刷回主内存了,这里大家不要和我一样钻牛角尖,之前我也在想,thread2把a修改了刷回主内存那thread1工作内存里a的值不就失效了?thread1已经修改完了就不会再去主内存中读a的值再修改一遍了,它现在要做的是把刚刚修改好a的值也刷回主内存,哦吼,这样一刷就出问题了。这就是voliate不能保证原子性也就是为什么不能保证并发安全的原因。

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

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/143940.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • JS中的indexOf方法

    JS中的indexOf方法indexOf()简介indexOf是js中内置的方法之一,它能

  • 信息收集之后_es日志收集

    信息收集之后_es日志收集一.摘要Censys提供了search、view、report、query、export以及data六种API接口。search接口的请求地址是https://www.censys.io/api/

  • SpringBoot的序列化和反序列化

    SpringBoot的序列化和反序列化序列化与反序列化1、认识序列化与反序列化Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程。2、为什么要实现对象的序列化和反序列化?(1)我们创建的Java对象被存储在Java堆中,当程序运行结束后,这些对象会被JVM回收。但在现实的应用中,可能会要求在程序运行结束之后还能读取这些对象,并在以后检索数据,这时就需要用到序列化。(2)当Java对象通过网络进行传输的时候。因为数据只能够以二进制的形式在网络中进行传输,因此当把对象通过网络发送

  • 可控硅工作原理及参数详解图_晶闸管和可控硅有什么区别

    可控硅工作原理及参数详解图_晶闸管和可控硅有什么区别原创:JackieLong转自:https://www.cnblogs.com/sunshine-jackie/p/8137469.html可控硅全称“可控硅整流元件”(SiliconControlledRectifier),简写为SCR,别名晶体闸流管(Thyristor),是一种具有三个PN结、四层结构的大功率半导体器件。可控硅体积小、结构简单、功能强,可起到变频、整流、逆变、…

    2022年10月22日
  • Silverlight ASP.NET control

    Silverlight ASP.NET control

  • GHO文件安装全教程

    GHO文件安装全教程首先写在前面,这里的使用情况是物理机安装,不是虚拟机安装,因尝试将GHO转换成ISO,然后再装虚拟机失败了(GHO文件过大的情况下,虚拟机CD加载不出来),所以直接装的物理机。目录1.PE盘制作的准备:2.系统分区:3.引导修复4.走到这里,恭喜你已经成功了哈????1.PE盘制作的准备:1.可选择的U盘启动方法很多,但我这边选择的是老毛桃:https://w…

发表回复

您的电子邮箱地址不会被公开。

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