以下内容来自经典Concurency in Practice
:
当线程A写入volatile变量并随后写入线程B. 读取相同的变量,所有变量的值 在写入volatile变量之前,A可见,变得可见 读取volatile变量后到B。
我不确定我是否真的能理解这句话。例如,在此上下文中所有变量的含义是什么?这是否意味着使用volatile
对非易失性变量的使用也有副作用?
在我看来,这句话有一些我无法理解的微妙含义
有什么帮助吗?
答案 0 :(得分:13)
您的问题的答案位于JLS #17.4.5:
在对该字段的每次后续读取之前发生对易失性字段(第8.3.1.4节)的写入。
因此,如果在一个帖子中你有
aNonVolatileVariable = 2 //w1
aVolatileVariable = 5 //w2
随后在另一个帖子中:
someVariable = aVolatileVariable //r1
anotherOne = aNonVolatileVariable //r2
即使该变量不是易变的,您也可以保证anotherOne
等于2。所以是的,使用volatile也会对非易失性变量的使用产生副作用。
更详细地说,这是由于Java内存模型(JMM)在同一部分中提供的另外两个保证:内部线程顺序和传递性( hb(x,y)表示 x发生在y 之前:
如果x和y是同一个线程的动作而x在程序顺序中位于y之前,那么 hb(x,y)。
[...]
如果 hb(x,y)和 hb(y,z),那么 hb(x,z)。
在我的例子中:
所以你可以通过传递性来得出 hb(w1,r2)。
如果JMM与之前发生的关系正确同步,则JMM保证程序的所有执行都是顺序一致的(即看起来没有任何重新排序)。因此,在这种特定情况下,非易失性读取可以保证看到非易失性写入的效果。
答案 1 :(得分:8)
这意味着如果您写入十个非易失性变量并写入易失性变量,则必须在易失性变量之前设置所有非易失性变量。
如果您阅读volatile变量和所有非易失性变量,您可以确保不会交换订单。