スレッドのタイトルは自明である必要があります...私はAtomicBoolean
クラスからの以下の方法の指定の間で少し混乱しています:
Java.util.concurrent.atomic.AtomicBoolean#compareAndSet
Java.util.concurrent.atomic.AtomicBoolean#getAndSet
私の強要は、if
条件でブール句として使用した場合、どちらも同じ動作になるということです。
public class Test {
private AtomicBoolean flag = AtomicBoolean(false);
public void processSomeAction() {
if (flag.getAndSet(false)) { // Shouldn't this be similar to flag.compareAndSet(false)
// process some action
}
}
//...
private void internalMutatorMethod() {
// do some staff then update the atomic flag
flas.set(true);
}
}
現在のフラグ値を取得して自動的に更新したい場合、両方の方法で同じ動作が発生するのではないでしょうか。
内部の違いが見当たらない場合は、それぞれをいつどのように使用するかについての説明をいただければ幸いです。
ドキュメント はかなり明確です。
getAndSet
->「指定された値に原子的に設定し、前の値を返します。」compareAndSet
-> "現在の値==期待値の場合、値を指定された更新値に原子的に設定します。"当然のことながら、compareAndSet
は2つの引数を取ります。
あなたの特定のケースでは:
if (flag.getAndSet(false))
は、前の値がflag
の場合にのみ、false
をtrue
に設定します。if (flag.compareAndSet(true, false))
と同等ですあなたはより良い理解のためにコードを見ることができます:
public final boolean getAndSet(boolean newValue) {
for (;;) {
boolean current = get();
if (compareAndSet(current, newValue))
return current;
}
}
getAndSet
では、古い値をget()
してからその値を変更しようとするまでの間にブール値が変更された場合、compareAndSet
はその値を変更しません値。したがって、getAndSet
は、ブール値が新しい値に設定されるまで、ループでcompareAndSet
を呼び出します。
あなたのコード例について:
flag.getAndSet(false)
は、AtomicBooleanの古い値を返します。一方、flag.compareAndSet(x,false)
(2つの引数があることに注意)は、AtomicBooleanが変更されたかどうかを返します。つまり、AtomicBooleanの古い値がxであったかどうかを返します。
実装を確認したところ、次のことがわかりました
public final boolean getAndSet(boolean newValue) {
for (;;) {
boolean current = get();
if (compareAndSet(current, newValue))
return current;
}
}
また、javadocをチェックするとき、compareAndSet
は比較に合格した場合にのみ値を設定し、getAndSet
は単に値を設定して前の値を返します。
スレッドは少し古いですが、getAndSetがcompareAndSetよりも効率的であるとは誰も言及していません。 CASは非常にコストのかかる命令です(すべてのCPUアーキテクチャ上で、JVMはここでは問題になりません)。したがって、それらは実際には同等ではありません。
したがって、OPに関しては、両方のメソッドが同じ動作を生成しますが、同じパフォーマンスは得られません。可能であればgetAndSetを使用してください。