6

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

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

最後の行で、メソッドはとの間の等値をwhile (!stats.compareAndSet(prev, newValue))どのように判断しますか? メソッドを実装するために必要なクラスはありますか? そうでない場合、なぜですか?javadoc には、次のように記載されていますcompareAndSetprevnewValueAccessStatisticsequals()AtomicReference.compareAndSet

現在の値 == 期待される値である場合、値を指定された更新された値にアトミックに設定します。

...しかし、このアサーションは非常に一般的なようで、AtomicReference で読んだチュートリアルでは、AtomicReference でラップされたクラスに equals() を実装することは決して提案されていません。

AccessStatisticsAtomicReference でラップされたクラスが equals() を実装する必要がある場合、私が考えているよりも複雑なオブジェクトの場合、オブジェクトを更新するメソッドを同期し、AtomicReference を使用しない方が速い場合があります。

4

4 に答える 4

6

== 演算子を使用した場合とまったく同じように参照を比較します。つまり、参照は同じインスタンスを指している必要があります。Object.equals() は使用されません。

于 2009-12-08T21:33:01.707 に答える
2

実際には、prev と newValue を比較しません!

代わりに、stats 内に保存されている値を prev と比較し、それらが同じ場合にのみ、stats 内に保存されている値を newValue に更新します。上記のように、等号演算子 (==) を使用してそうします。これは、prev が stats に格納されているものと同じオブジェクトを指している場合にのみ、stats が更新されることを意味します。

于 2011-12-12T14:03:42.900 に答える
0

オブジェクト参照の等価性 (別名 ==) をチェックするだけなので、参照を取得した後に AtomicReference が保持するオブジェクト参照が変更された場合、参照は変更されないため、最初からやり直す必要があります。

于 2009-12-08T21:31:57.217 に答える