2013-03-18 97 views
5

如果在Java中聲明一個成員變量爲volatile,這是否意味着所有對象的數據都存儲在易失性內存中,或者對該對象的引用存儲在易失性內存中?聲明一個對象是volatile的

例如,如果我有下面的類:

class C{ 
    int i = 0; 
    char c = 'c'; 
} 

如果我聲明它的一個實例如下:

private volatile C obj; 

這是否存儲參考到obj在易失性存儲器,或obj的數據(obj.iobj.cvolatile內存?

是否使obj.cobj.i線程安全?

+2

Java SE 6教程未指定'volatile'關鍵字作爲存儲對象在易失性內存中,但它確保讀取和寫入是原子性的。 http://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html – gerrytan 2013-03-18 21:51:55

+0

所有變量都存儲在易失性存儲器(即RAM)中,而不考慮volatile屬性。 http://en.wikipedia.org/wiki/Volatile_memory – 2013-03-19 00:02:19

+0

@gerrytan揮發性不是關於原子性,而是關於可見性。 – assylias 2013-03-22 08:47:13

回答

8

是隻有對象的引用將被認爲是由JVM揮發而不是對象數據本身將駐留在堆上。如果您需要在堆中對象的成員變量揮發您可以在關鍵字的過程適用於那些原語

class C { 
    volatile int i = 0; 
    volatile char c = 'c'; 
} 

回覆:您這是否使得可變線程安全的問題,取決於你如何使用變量。正如@gerrytan從Oracle文檔中指出的那樣,volatile關鍵字確實有助於讀取或寫入爲原子,但要警告的是,這不總是線程安全的。請看下面的代碼...

if(obj != null) { 
    obj.doSomething(); 
} 

它仍然是可能的,執行空校驗線程,被中斷它執行obj.doSomething()之前,另一個線程設置obj = null。此處需要其他一些機制,例如​​塊。

+0

偉大的答案:)謝謝! – user965369 2013-03-19 00:49:30

3
private volatile C obj; 

這將使只有obj易失性。

它使obj.c和obj.i線程安全嗎?

爲了使它們成爲線程安全的,您必須同步對它們的訪問。

+1

這反映了一個類的_instances_不是線程安全的一般原則; _classes_線程安全或不安全。 – 2013-03-18 22:01:20

2

這隻會使對象引用不穩定。 爲了使obj.i和obj.c也揮發性你必須讓他們揮發性明確

class C{ 
    volatile int i = 0; 
    volatile char c = 'c'; 
} 
1

如果您在Java中聲明成員變量爲volatile,這是否意味着所有對象的數據都存儲在易失性存儲器中,或者對該對象的引用存儲在易失性存儲器中?

當我們將對象聲明爲volatile時,我們實際上告訴底層處理器如何使用易失性對象。每次通過CPU指令讀取時,都會從堆中調用新副本,並且每次在對象將其保存到堆並可供其他線程使用。因此,處理器不會從緩存舊值中選取,也不會寫入緩存並等待緩存寫回堆。

它使obj.c和obj.i線程安全嗎? 不可以。只是保證你在閱讀對象時總是有一個新的副本。當你使用基於可變值的變量和處理邏輯時,有人可能已經改變了背景值和時間值你更新了它,你正在更新一個不同的值。