2012-07-15 43 views
1

假設你有下面的類的AtomicReference使用

public class AccessStatistics { 
    private final int noPages, noErrors; 
    public AccessStatistics(int noPages, int noErrors) { 
    this.noPages = noPages; 
    this.noErrors = noErrors; 
    } 
    public int getNoPages() { return noPages; } 
    public int getNoErrors() { return noErrors; } 
} 

,你執行下面的代碼

private AtomicReference<AccessStatistics> stats = 
    new AtomicReference<AccessStatistics>(new AccessStatistics(0, 0)); 

public void incrementPageCount(boolean wasError) { 
    AccessStatistics prev, newValue; 
    do { 
    prev = stats.get(); 
    int noPages = prev.getNoPages() + 1; 
    int noErrors = prev.getNoErrors; 
    if (wasError) { 
     noErrors++; 
    } 
    newValue = new AccessStatistics(noPages, noErrors); 
    } while (!stats.compareAndSet(prev, newValue)); 
} 

在最後兩行

newValue = new AccessStatistics(noPages, noErrors); 
while (!stats.compareAndSet(prev, newValue)) 

這是否意味着新創建AccessStatistics實例與當前的AccessStatistics實例具有相同的引用。怎麼會這樣 ?任何人都可以解釋它。非常感謝。

回答

3

stats.compareAndSet(prev, newValue)將失敗並返回false如果stats保存的當前參考不是prev

通常,在多線程環境中,在prev = stats.get();stats.compareAndSet(prev, newValue);之間很可能有另一個線程修改了stats所保存的引用。

stats.compareAndSet(prev, newValue);真說:

    如果 stats仍持有至 prev一個參考,因爲它之前的5個係爲
  • ,更新它持有的引用,newValue
  • 然而,如果另一個線程已經改變了參考自從我上次檢查5行前,由stats持有,放棄我的計算並循環重新計算新的newValue
+0

我也在Java Spec幫助文檔中找到答案。非常感謝 – 2012-07-15 16:14:08

0

新創建的對象是新的。在創建該行後,唯一指向它的是newValue。沒有其他的可以 - 它怎麼可能? compareAndSet()只設置,如果沒有其他設置爲第三個值,除了你知道的舊的prev和新的newValue

+0

很好的答案。再次感謝。 – 2012-07-15 16:19:27