2012-11-28 43 views
7

從文檔:使用volatile關鍵字時的內存一致性錯誤示例?

使用volatile變量降低了內存一致性錯誤

但是,這意味着有時volatile變量不工作正確的風險? 奇怪的是如何使用它 - 我認爲這是非常糟糕的代碼有時工作有時不會。我試圖谷歌,但沒有發現揮發性示例內存一致性錯誤。你能提出一個嗎?

+1

我強烈建議您閱讀Brian Goetz的「實踐中的Java併發性」。它在亞馬遜:http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601/ref=sr_1_1?ie=UTF8&qid=1354080774&sr=8-1&keywords=java+concurrency+in+practice –

+0

這本書是一本很好的書,它可以揭開與Java的內存和線程模型有關的所有內容。 –

回答

10

問題不在於volatile工作不可靠。它總是按照它應該工作的方式工作。問題在於它應該工作的方式有時不足以實現併發控制。如果在錯誤的情況下使用volatile,仍可能出現內存一致性錯誤。

A volatile變量將始終有任何寫入傳播到所有線程。但是,假設您需要在各個線程之間增加變量。這樣做(*)

volatile int mCounter; 

// later, in some code that might be executed simultaneously on multiple threads: 
mCounter++; 

有一個機會,計數器增量將被錯過。這是因爲在寫入新值之前,每個線程需要首先讀取mCounter的值。在這兩個步驟之間,另一個線程可能已經更改了mCounter的值。在這種情況下,您需要依靠​​塊而不是volatile來確保數據完整性。

有關volatile與​​更多的信息,我Brian Goetz撰寫推薦文章Managing volatility

(*)我意識到,上面會更好地AtomicInteger執行;這是一個人爲的例子來說明一個觀點。

4

揮發性執行以下操作:

-防止緩存值的主題。

-它確保具有對象字段值的副本的線程與存儲器中存在的主副本一致。

-確保數據直接寫入存儲器並從存儲器本身讀取。

##但是,在揮發性失敗條件:

-製作Non-Atomic statement Volatile

如:

int count = 0; 

count++; // Increment operator is Not Atomic in java 

##更好的選擇:

它總是更好地遵循Brian's Rule

When ever we write a variable which is next to be read by another thread, or when we are reading a variable which is written just by another thread, it needs to be synchronized. The shared fields must be made private, making the read and write methods/atomic statements synchronized.

2.第二個選擇是使用Atomic Classes,像的AtomicInteger,AtomicLong的,的AtomicReference等

##看到這個鏈接,我都問你們這樣一個類似的問題:

Why Volatile is behaving weirdly