可变变量和其他变量
2022-09-03 13:23:29
以下是来自经典:Concurency in Practice
当线程 A 写入易失性变量,随后线程 B 读取同一变量时,在写入易失性变量之前对 A 可见的所有变量的值在读取易失性变量后对 B 可见。
我不确定我是否真的能理解这句话。例如,在此上下文中所有变量的含义是什么?这是否意味着使用对使用非易失性变量也有副作用?
在我看来,这句话有一些我无法理解的微妙含义。
有什么帮助吗?volatile
以下是来自经典:Concurency in Practice
当线程 A 写入易失性变量,随后线程 B 读取同一变量时,在写入易失性变量之前对 A 可见的所有变量的值在读取易失性变量后对 B 可见。
我不确定我是否真的能理解这句话。例如,在此上下文中所有变量的含义是什么?这是否意味着使用对使用非易失性变量也有副作用?
在我看来,这句话有一些我无法理解的微妙含义。
有什么帮助吗?volatile
您的问题的答案在 JLS #17.4.5 中:
对易失性字段 (§8.3.1.4) 的写入发生在每次后续读取该字段之前。
因此,如果在一个线程中,您有
aNonVolatileVariable = 2 //w1
aVolatileVariable = 5 //w2
随后在另一个线程中:
someVariable = aVolatileVariable //r1
anotherOne = aNonVolatileVariable //r2
您可以保证该变量将等于 2,即使该变量不是易失性的。所以,是的,使用易失性也会对非易失性变量的使用产生副作用。anotherOne
更详细地说,这是由于 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保证,如果程序的所有执行与发生前关系正确同步,则程序的所有执行都将按顺序一致(即看起来没有任何内容被重新排序)。所以在这种特定情况下,非易失性读取保证看到非易失性写入的效果。
这意味着,如果您写入十个非易失性变量并写入易失性变量,则必须在易失性变量之前设置所有非易失性变量。
如果您阅读易失性变量和所有非易失性变量,则可以确保订单不会被交换。