次のクラスがあるとします
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 には、次のように記載されていますcompareAndSet
prev
newValue
AccessStatistics
equals()
AtomicReference.compareAndSet
現在の値 == 期待される値である場合、値を指定された更新された値にアトミックに設定します。
...しかし、このアサーションは非常に一般的なようで、AtomicReference で読んだチュートリアルでは、AtomicReference でラップされたクラスに equals() を実装することは決して提案されていません。
AccessStatistics
AtomicReference でラップされたクラスが equals() を実装する必要がある場合、私が考えているよりも複雑なオブジェクトの場合、オブジェクトを更新するメソッドを同期し、AtomicReference を使用しない方が速い場合があります。