2012-07-15 40 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