2011-02-03 56 views
22

我們在我們的一個項目中使用volatile來維護不同線程訪問的變量的相同副本。我的問題是使用volatilestatic是否合適。編譯器不會給出任何錯誤,但我不明白使用兩者的原因。Java中的「volatile」是什麼意思?

回答

17

對於讀取存儲器型號規格的短小,我建議您閱讀http://jeremymanson.blogspot.com/2008/11/what-volatile-means-in-java.html。它由JMM作者之一編寫,應該回答你的問題。根據happens-before條款考慮讀寫內存也是有幫助的; JMM for Java 5開始在語義之前添加volatile

具體來說,當您從一個線程讀取volatile變量時,所有寫入幷包括從其他線程寫入該volatile變量的變量現在都可以看到該線程。如果您有一段時間,Google技術講座將進一步討論主題:https://code.google.com/edu/languages/#_java_memmodel

而且,是的,您可以使用staticvolatile。他們做不同的事情。

+0

關於你的第二個段落的更新值:你的意思是所有寫入到所有變量,或全部寫入到一個volatile變量? – fredoverflow 2011-05-29 09:56:50

+0

我相信這是在最後一次寫入正在讀取的volatile變量之前寫入所有變量。 – ide 2011-06-04 01:22:38

7

volatile表示該變量在運行時發生更改,並且編譯器不應該因任何原因而緩存其值。

在線程之間共享變量時,這實際上只是一個問題,您不希望線程使用過時的數據,因此編譯器不應該緩存變量引用的值。

10

在Java中,volatile具有與它在C中一樣的一般含義.Java Memory Model(請參閱ide的答案中的出色鏈接)允許線程在標記爲非的變量的同時「看到」一個不同的值-volatile。例如:

主題一:

n = 1; 
// wait... 
n = 2; 

線程B和C:

while (true) { 
    System.out.println(name + ": " + n); 
} 

這個輸出是不允許發生的(請注意,你不能保證B和C之間交替嚴格,我只是試圖在這裏顯示B和C的「轉換」):

C: 1 
B: 1 
C: 2 
B: 1 
C: 2 
B: 2 

這是完全獨立於鎖所採取的println;線程B是允許看到n作爲1,即使在C發現它是2之後。有很多很好的理由,我不能假裝完全理解,很多與速度有關,有些與安全有關。

如果它是不穩定的,你保證(除了println的鎖定,我暫時忽略),B和C將同時「看到B的新值,只要它是發送。

您可以使用volatilestatic,因爲它們影響不同的事情。 volatile原因改變一個變量被「複製」到所有線程他們使用它之前使用該變量,而static股在所有一個變量使用這個變量。(這對新加入Java的人來說可能會相當困惑,因爲每個Thread恰好都是作爲class實現的。)

2

易失性用於許多不同的情況,其中多個線程需要訪問相同的變量。許多不做多線程/併發編程的人不會接觸到這一點。易失性確保變量始終從主內存中讀取,而不是從緩存/寄存器版本中讀取。易失性本身並不是一個鎖,因爲所有線程一旦寫入就會看到這些更改並不意味着您可以用原子方式進行比較和交換。 但是,此功能可以與其他功能一起使用,如比較和交換,以構建線程安全的數據結構,而不需要用戶使用「更重」的java wait-notify語義。

,你可以得到更多信息此鏈接 http://www.quora.com/Threading-in-Java/What-is-the-purpose-of-the-volatile-keyword-in-java

1

考慮這樣一個場景,當兩個線程(線程1和線程)正在訪問相同的變量「mObject」,值爲1

上,當線程1運行時,它不希望其他線程修改變量'mObject'。在這種情況下,Thread1緩存值爲1的變量'mObject'。

如果Thread2將'mObject'的值修改爲2,那麼Thread1會將mObject值作爲1來引用,因爲它進行了緩存。 爲了避免這種緩存,我們應該聲明變量爲

private volatile int mObject;

在此scenarion的線程1將越來越mObject