您的问题的答案在JLS#17.4.5中:
在随后每次对该字段进行读取之前,都会写入一个易失字段(第8.3.1.4节)。
所以如果在一个线程中
aNonVolatileVariable = 2 //w1aVolatileVariable = 5 //w2
然后在另一个线程中:
someVariable = aVolatileVariable //r1anotherOne = aNonVolatileVariable //r2
anotherOne即使该变量不是volatile,您也可以保证等于2。因此,是的,使用volatile对使用非易失性变量也有副作用。
更详细地讲,这是由于同一部分中的Java内存模型(JMM)提供了2个其他保证:线程内顺序和可传递性(hb(x,y)表示x发生在y之前):
如果x和y是同一线程的动作,并且x按程序顺序位于y之前,则hb(x,y)。
[…]
如果hb(x,y)和hb(y,z),则hb(x,z)。
在我的示例中:
- hb(w1,w2)和hb(r1,r2)(线程内语义)
- hb(w2,r1)由于易失性保证
因此可以通过传递性得出hb(w1,r2)的结论。
而且,JMM保证,如果程序与事前发生的关系正确同步,则该程序的所有执行将保持顺序一致(即看起来好像没有任何重排序)。因此,在这种特定情况下,可以保证非易失性读取可以看到非易失性写入的效果。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)