這是兩個原子操作:什麼是原子?
int value = 5;
Object obj = new Object();
但使用原語作爲方法參數時,這會被認爲是一個原子操作:
? 對象引用的副本不是原子的,因爲它包含讀取和寫入,對吧?
難道是正確的說,只有這樣,才能使對對象引用的原子操作是宣佈它爲空或指定一個新的對象吧,如:
Object obj = null;
和
Object obj = new Object();
?
這是兩個原子操作:什麼是原子?
int value = 5;
Object obj = new Object();
但使用原語作爲方法參數時,這會被認爲是一個原子操作:
? 對象引用的副本不是原子的,因爲它包含讀取和寫入,對吧?
難道是正確的說,只有這樣,才能使對對象引用的原子操作是宣佈它爲空或指定一個新的對象吧,如:
Object obj = null;
和
Object obj = new Object();
?
如果上述方法中的參數是對象的引用,那麼該操作不會是原子的,對嗎?
一般來說,這是正確的。一個好的經驗法則是要考慮有沒有原子可言,甚至像原語:
int b,c;
int a = ++b - c;
只有原語,但整個分配潛力不是原子。
如果您需要enshure原子操作,你有diferent posibilities:
public synchronized void setValue(int val, Object obj)
現在整個功能是「原子」這學期我還沒有看到在Java中使用
當一個線程使用一個變量的值時,其獲得的值實際上通過該線程或通過一些其它線程存儲到變量的值。即使程序不包含正確同步的代碼,情況也是如此。例如,如果兩個線程將對不同對象的引用存儲到同一個引用值中,則該變量將隨後包含對一個對象或另一個對象的引用,而不是對某個其他對象的引用或已損壞的引用值。
所以分配是原子。
當一個線程讀取原始的值(除了長和雙),或一個對象引用的,它看到它在這個變量設定了值,或者另一個線程在該變量設定的值。
然而,儘管在一個線程中值分配給共享變量是原子,這並不意味着所有其他線程會後馬上看到新的價值。爲此,該變量應該被聲明爲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
調用不是原子的。
謝謝你提到「之前會發生」的關係。 – dmeister
感謝您的回答!我還編輯了我的問題,以便它在方法調用中使用對象引用時包含代碼示例。 – Rox