2011-06-04 134 views
4

我知道Java中的volatile關鍵字可以對引用變量和除long和double之外的所有基本類型(原子性)進行讀/寫操作。關於引用類型的Java volatile關鍵字的問題

我也知道像遞增整數var ++這樣的複合語句不是原子的,不應該用來代替synchronized語句。

但是這個班呢?

public class Setter{ 

private int num = 0; 

public int setNum(int numIn){ 
num = numIn; 
return num; 
} 
} 

現在說你聲明一個Setter的實例爲volatile。

public class Main { 
    private volatile Setter s; 

public static void main(String[] args){ 
    s = new Setter(); 
    s.setNum(5); 
} 
} 

是調用方法setNum atomic?如果多個線程同時調用它們,每個具有不同的值,這個語句是否安全?

以適當的方式使用volatile類並在不安全的複合語句中使用volatile類的例子是什麼?

+0

第一句話不是一個句子,這使得不可能清楚地解釋問題的其餘部分。 – bmargulies 2011-06-04 14:31:27

+0

@bmargulies:然後解釋爲什麼它是錯誤的(是的,我知道這是錯誤的),或者使用你的mod點來編輯問題,而不是做一個snarky評論。你也意識到是否你的評論不再有任何意義了,如果這個問題得到編輯和第一句話改變了嗎?像/ SO這樣的問題/維基風格編輯。你說它*******? – SyntaxT3rr0r 2011-06-04 17:49:23

+0

你誤解了Java中的volatile *(這是bmargulies拙劣地試圖解釋的)。首先,如果聲明* volatile long ... *,您將永遠無法讀取長「半集」(例如,從一個線程設置32-hi位,從另一個線程設置32-lo位)。那根本不可能發生。 – SyntaxT3rr0r 2011-06-04 17:53:25

回答

3

是調用方法setNum atomic?

不,它不是。只有對s的讀/寫操作是易變的。

這可以與讓Listfinal進行比較。這不足以使列表不可變,只有列表引用本身。

+0

感謝您清除它 – stack356 2011-06-04 18:17:55

1

不,使用volatile僅適用於參考s,而不適用於它所指對象的字段。你不能(安全地)有多個線程調用s.setNum(n)

但是,您可以創建一個新的Setter對象,並在其中存儲一個數字,然後將s更改爲引用新對象而不是舊對象。

1

對象的引用和該對象的內容是不同的東西。在您的情況下,對象的參考(是您的主要類別)是volatile,這意味着當您讀取/寫入引用時,將應用不穩定的規則。你可以自由地有另一個參考,這個對象不是易失性的,而且它的規則不會適用於它。