1

次のクラスがあるとします

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));
}

最後の 2 行で

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

新しく作成された AccessStatistics インスタンスが現在の AccessStatistics インスタンスと同じ参照を持っていることを意味しますか? どうしてですか?誰でも説明できますか?どうもありがとう。

4

2 に答える 2

3

stats.compareAndSet(prev, newValue)statsが保持している現在の参照が でない場合、 は失敗して false を返しますprev

通常、マルチスレッド環境では、prev = stats.get();stats.compareAndSet(prev, newValue);別のスレッドが によって保持されている参照を変更する可能性が非常に高くなりstatsます。

stats.compareAndSet(prev, newValue);本当に言います:

  • statsへの参照がまだ保持されている場合prevは、5 行前のように、への参照を保持するように更新します。newValue
  • ただし、5 行前に最後にチェックしてから別のスレッドが保持している参照を既に変更している場合はstats、計算を破棄してループし、新しい を再計算しますnewValue
于 2012-07-15T15:56:50.287 に答える
0

新しく作成されたオブジェクトは、まあ、新しいです。それが作成された行の後、それを参照するのはnewValue. 他に何もできませんでした-どうしてできるのでしょうか? compareAndSet()あなたが知っている古いものとprevあなたが作った新しいものに加えて、その間に他に何も設定されていない場合にのみ、3番目の値に設定しますnewValue

于 2012-07-15T15:57:25.880 に答える