AtomicReference用法

时间:2012-07-15 15:50:19

标签: java multithreading compare-and-swap

假设你有以下课程

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实例具有相同的引用。怎么会这样 ?任何人都可以解释它。非常感谢。

2 个答案:

答案 0 :(得分:3)

如果stats.compareAndSet(prev, newValue)保留的当前引用不是stats

prev将失败并返回false。

通常,在多线程环境中,prev = stats.get();stats.compareAndSet(prev, newValue);之间的另一个线程很可能会修改stats所持有的引用。

stats.compareAndSet(prev, newValue);真的说:

  • 如果stats仍然保留对prev的引用,因为之前是5行,请更新它以保留对newValue的引用
  • 如果自上次检查5行以来另一个线程已经更改了stats所持有的引用,则放弃我的计算并循环以重新计算新的newValue

答案 1 :(得分:0)

新创建的对象是新的。在创建它的行之后,唯一引用它的是newValue。没有别的可能 - 怎么可能? compareAndSet()仅设置,如果没有其他内容同时将其设置为第三个值,除了您所知道的prev以及您创建的新newValue之外的其他值。