2012-12-03 46 views
16

我最近在一次演講中聽到,對volatile進行寫操作會觸發線程寫入的每個變量的內存屏障。這真的是對的嗎?從JLS看來,似乎只有相關的變量會被刷新,而不是其他的。有人知道實際上是正確的嗎?有人能指出我在JLS的具體位置嗎?是對Java中volatile變量的內存屏障的寫入

+1

我對JLS的解釋與你的一致。 – NPE

+1

[volatile變量和其他變量]的可能重複(http://stackoverflow.com/questions/12438464/volatile-variables-and-other-variables) – assylias

+0

正如答案所闡明的那樣,它不僅僅是聲明爲volatile的變量,所有寫入發生在易失性寫入之前。 – sjlee

回答

1

Volatile variables and other variables參考是正確的。我沒有意識到發生的傳遞性 - 之前是VM必須執行的事情,而不是定義中的事情。我仍然不明白爲什麼某些具有如此深遠影響的事物沒有明確說明,實際上是某種定義的必然結果。要包起來:假設你有4個動作是這樣的:

thread1  thread2 
a1 
a2 
       a3 
       a4 

其中A2是一個volatile變量v和A3寫是從同一揮發性變量v讀 它的發生在definiton如下(hb)表示hb(a1,a2)和hb(a3,a4)。 另外,對於揮發物我們有hb(a2,a3)。現在從hb所需的傳遞性hb(a1,a3)開始。因此,易失性變量v的寫入和後續讀取用作內存屏障。

16

是的,它會啓動一個障礙。您可以閱讀更多here。有4種類型,LoadLoad LoadStore StoreStore StoreLoad。

至於你的問題

從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

+1 *「與其他線程加載這個新商店的謂詞」* – assylias

+4

我認爲你的例子是錯誤的。線程2不需要比較'a'到3來查看'b'的新值,讀取'a'就足夠了。因此,在第一行之後,Thread-2保證看到「b」等於10(在所有分支中)。但是,從不讀取'a'的第三個線程不保證看到'b'的新值。 –

+11

@PhilippWendler我認爲重點是:如果a == 0,寫入'a = 3'還沒有發生,b可以是任何東西,包括10.如果a == 3,寫入'a = 3'發生了並且你保證有b == 10. – assylias