我最近在一次演讲中听到,写入volatile会触发线程写入的每个变量的内存屏障。这是真的正确吗?从JLS看来,似乎只有相关的变量才被刷新,而其他变量则没有。有人知道什么是正确的吗?可以指出我在JLS中的具体位置吗?
答案 0 :(得分:21)
是的,它会引发障碍。您可以阅读更多here。 LoadLoad LoadStore StoreStore StoreLoad有4种类型。
就你的问题而言
从JLS看来,只有相关变量才会被刷新 出来,但不是其他人。有人知道什么是正确的吗?
在易失性存储之前发生的所有写入都可由任何其他线程看到,其他线程加载此新存储。但是,如果不加载新值,则在易失性加载之前发生的写入可能会或可能不会被其他线程看到。
一个实际的例子
volatile int a =0;
int b = 0;
Thread-1
b = 10;
a = 3;
Thread-2
if(a == 0){
// b can b 10 or 0
}
if(a == 3){
// b is guaranteed to be 10 (according to the JMM)
}
答案 1 :(得分:3)
对Volatile variables and other variables的引用是正确的。我没有意识到发生之前的传递性是必须由VM实现的,而不是从定义中得到的东西。我仍然感到困惑的是,为什么具有如此深远影响的事情没有明确说明,但实际上是某种定义的必然结果。包装起来:假设你有4个这样的动作:
thread1 thread2
a1
a2
a3
a4
其中a2是对易失性变量v的写入,而a3是对同一易失性变量v的读取。 它遵循hb(a1,a2)和hb(a3,a4)之前发生的定义(hb)。 此外,对于挥发物,我们有hb(a2,a3)。现在来自hb所需的传递性hb(a1,a3)。因此,对易失性变量v的写入和后续读取将起到内存屏障的作用。