[英]Volatile variable in Java
所以我正在阅读这本名为Java Concurrency in Practice的书,我坚持这个解释,如果没有一个例子,我似乎无法理解。 这是引用:
当线程
A
写入易失性变量并且随后线程B
读取相同的变量时,在写入易失性变量之前,A
可见的所有变量的值在读取volatile变量后变为B
可见。
有人可以给我一个反例,说明为什么“在写入易变量之前A
可见的所有变量的值在读取易变量后变为B
可见”?
我很困惑为什么在读取volatile变量之前所有其他非易失性变量都不会被B
看到?
声明一个易变的Java变量意味着:
仅供参考,何时需要挥发性?
当多个线程使用相同的变量时,每个线程将拥有自己的该变量的本地缓存副本。 因此,当它更新值时,它实际上在本地缓存中更新,而不是在主变量内存中更新。 使用相同变量的另一个线程对另一个线程更改的值一无所知。 要避免此问题,如果将变量声明为volatile,则它不会存储在本地缓存中。 每当线程更新值时,它都会更新到主存储器。 因此,其他线程可以访问更新的值。
来自JLS§17.4.7 良好的执行
我们只考虑结构良好的执行。 如果满足以下条件,则执行E = <P,A,po,so,W,V,sw,hb>形成良好:
每次读取都会在执行中看到对同一变量的写入。 易失性变量的所有读写都是易失性动作。 对于A中的所有读取r,我们在A和W(r)中有W(r).v = rv当且仅当r是易失性读取时,变量rv是易失性的,并且当且仅当w时,变量wv是易失性的是一个易变的写。
发生在订单之前是部分订单。 发生前 - 顺序是通过与边缘和程序顺序同步的传递闭包给出的。 它必须是有效的偏序:反身,传递和反对称。
执行遵循线程内一致性。 对于每个线程t,由A中的t执行的动作与该线程在隔离的程序顺序中生成的动作相同,每个写入写入值V(w),假设每个读取r看到值V( W(R))。 每次读取所见的值由存储器模型确定。 给出的程序顺序必须反映根据P的线程内语义执行动作的程序顺序。
执行是在一致之前发生的(§17.4.6)。
执行遵循同步顺序一致性。 对于A中的所有易失性读取r,情况并非如此(r,W(r))或存在写入获胜A,使得wv = rv等等(W(r),w)等等( w,r)。
有用的链接: 我们真正了解Java中的非阻塞并发性?
线程B可能具有这些变量的CPU本地缓存。 读取volatile变量可确保观察到从先前写入volatile的任何中间缓存刷新。
有关示例,请阅读以下链接,其中以“使用易失性修复双重检查锁定”结束:
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
如果变量是非易失性的,则编译器和CPU可以根据需要自由地重新排序指令,以便优化性能。
如果变量现在声明为volatile,则编译器不再尝试优化对该变量的访问(读取和写入)。 但是,它可以继续优化其他变量的访问。
在运行时,当访问volatile变量时,JVM会为CPU生成适当的内存屏障指令。 内存屏障具有相同的用途 - CPU也可以防止重新排序指令。
当一个volatile变量写入(通过线程A)时,所有对任何其他变量的写操作都会完成(或者至少会显示),并且在写入volatile变量之前对A可见; 这通常是由于内存写入屏障指令。 同样,对其他变量的任何读取都将在读取之前完成(或将显示为)(通过线程B); 这通常是由于内存读屏障指令。 这种由屏障强制执行的指令排序将意味着对A可见的所有写入都将是可见的B.然而,这并不意味着没有发生任何指令的重新排序(编译器可能已执行)重新订购其他指示); 它只是意味着如果A发现任何可见的写入,它就会对B可见。简单来说,这意味着不保持严格的程序顺序。
如果您想更详细地了解JVM如何发布内存屏障指令,我将在内存屏障和JVM并发上指出这篇文章。
相关问题
允许线程缓存其他线程自更新以来可能具有的变量值。 volatile
关键字强制所有线程不缓存值。
如果你使用volatile变量,这只是内存模型给你的额外奖励。
通常(即,在没有volatile变量和同步的情况下),VM可以按照它想要的任何顺序将变量从一个线程可见到其他线程,或者根本不存在。 例如,阅读线程可以读取另一个线程变量赋值的早期版本的混合。 这是因为线程可能在具有自己的高速缓存的不同CPU上运行,这些高速缓存有时仅被复制到“主存储器”,并且还通过代码重新排序以用于优化目的。
如果你使用了一个volatile变量,一旦线程B从中读取了一些值X,VM就会确保线程A在写入X之前写入的任何内容对于B也是可见的。(以及A保证为可见的所有内容) ,传递)。
对同步块和其他类型的锁给出了类似的保证。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.