2011-11-10 92 views
3

這是兩個原子操作:什麼是原子?

int value = 5; 
Object obj = new Object(); 

但使用原語作爲方法參數時,這會被認爲是一個原子操作: ​​

? 對象引用的副本不是原子的,因爲它包含讀取和寫入,對吧?

難道是正確的說,只有這樣,才能使對對象引用的原子操作是宣佈它爲空或指定一個新的對象吧,如:

Object obj = null; 

Object obj = new Object(); 

回答

4

如果上述方法中的參數是對象的引用,那麼該操作不會是原子的,對嗎?

一般來說,這是正確的。一個好的經驗法則是要考慮有沒有原子可言,甚至像原語:

int b,c; 
int a = ++b - c; 

只有原語,但整個分配潛力不是原子。

如果您需要enshure原子操作,你有diferent posibilities:

  • synchronized塊
  • 不可變對象
  • 特定庫(java.util.concurrent.atomic中)
+0

感謝您的回答!我還編輯了我的問題,以便它在方法調用中使用對象引用時包含代碼示例。 – Rox

0
public synchronized void setValue(int val, Object obj) 

現在整個功能是「原子」這學期我還沒有看到在Java中使用

1
To the JLS!

當一個線程使用一個變量的值時,其獲得的值實際上通過該線程或通過一些其它線程存儲到變量的值。即使程序不包含正確同步的代碼,情況也是如此。例如,如果兩個線程將對不同對象的引用存儲到同一個引用值中,則該變量將隨後包含對一個對象或另一個對象的引用,而不是對某個其他對象的引用或已損壞的引用值。

所以分配是原子。

3

當一個線程讀取原始的值(除了長和雙),或一個對象引用的,它看到它在這個變量設定了值,或者另一個線程在該變量設定的值。

然而,儘管在一個線程中值分配給共享變量是原子,這並不意味着所有其他線程會後馬上看到新的價值。爲此,該變量應該被聲明爲volatile。 volatile還會使寫入操作變得冗長和雙重原子。不過,我更喜歡在這種情況下使用AtomicXxx(AtomicLong,AtomicBoolean等)。

如果你想自動更改兩個共享變量的值,那麼你應該使用唯一鎖來同步每個訪問(讀寫)這些變量。此外,每個「檢查然後行動」或「讀取然後寫入」操作是非原子的。這意味着這些操作也需要同步:

a++; // read a, increment value, write value to a 
if (a > 0) {a = b;} // check value of a, then assign new value to a. 

您的問題中的每一個操作都是原子操作。但在setValue()中,您有兩個原子操作。整個setValue調用不是原子的。

+0

謝謝你提到「之前會發生」的關係。 – dmeister