Java中的Volatile变量
因此,我正在阅读这本名为《实践中的Java并发性》的书,我被困在这一解释上,如果没有一个例子,我似乎无法理解这一解释。以下是报价: 当线程Java中的Volatile变量,java,multithreading,concurrency,volatile,Java,Multithreading,Concurrency,Volatile,因此,我正在阅读这本名为《实践中的Java并发性》的书,我被困在这一解释上,如果没有一个例子,我似乎无法理解这一解释。以下是报价: 当线程A写入volatile 变量和后续线程B 读取相同的变量,即值 在所有可见的变量中 A在写入volatile之前 变量在B之后变为可见 读取可变变量 有人能给我一个反例,说明为什么“在写入可变变量之前,a可见的所有变量的值在读取可变变量之后,B可见” 我不明白为什么在读取易失性变量之前,所有其他非易失性变量对B不可见?声明易失性Java变量意味着: 这个变量
A
写入volatile
变量和后续线程B
读取相同的变量,即值
在所有可见的变量中
A
在写入volatile之前
变量在B
之后变为可见
读取可变变量
有人能给我一个反例,说明为什么“在写入可变变量之前,a
可见的所有变量的值在读取可变变量之后,B
可见”
我不明白为什么在读取易失性变量之前,所有其他非易失性变量对
B
不可见?声明易失性Java变量意味着:
- 这个变量的值永远不会被本地线程缓存:所有读写操作都将直接进入“主内存”
- 对变量的访问就像它被封装在一个同步块中一样,在其自身上是同步的李>
的形式良好 如果以下条件为真:
有用链接:线程B可能有这些变量的CPU本地缓存。读取volatile变量可确保观察到从先前写入volatile的任何中间缓存刷新 例如,阅读以下链接,该链接以“使用Volatile修复双重检查锁定”结尾:
允许线程缓存其他线程在读取变量值后可能已更新的变量值。
volatile
关键字强制所有线程不缓存值。如果使用volatile变量,这只是内存模型给您的额外奖励
通常(即,在没有易失性变量和同步的情况下),VM可以使一个线程中的变量以它想要的任何顺序对其他线程可见,或者根本不可见。例如,读取线程可以读取其他线程变量赋值的早期版本的混合。这是由于线程可能运行在具有自己缓存的不同CPU上,这些缓存有时仅复制到“主内存”,此外,为了优化目的,代码重新排序也会导致这种情况
如果您使用了一个易失性变量,只要线程B从中读取某个值X,VM就会确保线程a在写入X之前写入的任何内容对B也是可见的(以及保证a是可见的、可传递的)
对于同步块和其他类型的锁也提供了类似的保证。如果变量是非易失性的,那么编译器和CPU可以根据自己的需要自由地重新排序指令,以优化性能 如果变量现在声明为volatile,则编译器不再尝试优化对该变量的访问(读写)。然而,它可能会继续优化对其他变量的访问 在运行时,当访问易失性变量时,JVM会向CPU生成适当的内存屏障指令。内存屏障的作用是相同的——CPU还可以防止指令重新排序 当一个易失性变量被写入(通过线程a)时,对任何其他变量的所有写入都已完成(或至少看起来是这样),并且在写入易失性变量之前对a可见;这通常是由于内存写屏障指令造成的。同样,对其他变量的任何读取都将在 读取(通过线程B);这通常是由于我的错误