5

呼び出しの間に違い(または起こりうる副作用)があるかどうか疑問に思います:

AtomicBoolean.set(true)

AtomicBoolean.compareAndset(false, true)

状態のJavaDoc AtomicBoolean#set

無条件に指定された値に設定されます。

状態中AtomicBoolean#compareAndSet

現在の値==期待値の場合、原子的に値を指定された更新された値に設定します。

どちらの場合も、値はtrueに設定されます。では、違いは何ですか?

4

5 に答える 5

10

compareAndset(false, true)false値がすでにの場合は戻りますtrue
実際にはと同等!getAndSet(true)です。

于 2012-11-13T15:41:32.433 に答える
6

あなたが引用したテキストは、2つの操作の違いが何であるかを明確に示しています。しかし、明確にするために、原子性の側面を無視すると、最初の側面は次のようになります。

public void set(boolean newValue) {
    this.value = newValue;
}

2番目のものは次のものと同等です。

public boolean compareAndSet(boolean expected, boolean newValue) {
    if (this.value == expected) {
        this.value = newValue;
        return true;
    } else {
        return false;
    }
}

たとえばset(true)、状態をtrueに設定し、まだ存在しない場合compareAndset(false, true)は状態をに設定します。したがって、はい、状態への正味の影響は同じです。 truetrueAtomicBoolean

returnただし、オブジェクトの初期状態によって値が異なることに気付くでしょうAtomicBoolean...そのため、これらの引数値を使用しても、メソッドは同等ではありません。

于 2012-11-13T15:45:23.093 に答える
3

パフォーマンスの観点から答えを探してここに着陸しました。ネイティブ実装と決定ブロックについて確信が持てなかったため、同じことを評価するコードを書くことになりました。結果ごとに、set()は複数の決定ブロックを通過しないため、間違いなくパフォーマンスの優位性があります。以下のコードと出力を見つけてください。

public static void main(String[] args) {
    boolean curValue = true;
    boolean dummyValue = true;
    int attempts = Integer.MAX_VALUE;


    AtomicBoolean test = new AtomicBoolean(curValue);
    long start = System.currentTimeMillis();
    for(int i=0; i<attempts; i++){
        test.set(true);
        dummyValue = !dummyValue;
    }
    System.out.println("time taken for set: "+(System.currentTimeMillis()-start));

    start = System.currentTimeMillis();
    for(int i=0; i<attempts; i++){
        test.compareAndSet(curValue, curValue); // always set the same value
        dummyValue = !dummyValue;
    }
    System.out.println("time taken for compareAndSet - same value case: "+(System.currentTimeMillis()-start));

    curValue = !curValue;
    start = System.currentTimeMillis();
    for(int i=0; i<attempts; i++){
        test.compareAndSet(curValue, !curValue); // always invert
        curValue = !curValue;
    }
    System.out.println("time taken for compareAndSet - inversion case: "+(System.currentTimeMillis()-start));
}

出力:

time taken for set: 2689
time taken for compareAndSet - same value case: 15559
time taken for compareAndSet - inversion case: 14802
于 2015-02-26T07:42:10.220 に答える
0

AtomicBooleanのset()メソッドとcompareAndSet()メソッドの違いは、スレッドロックメカニズムにあります。

スレッドの安全性は、次のコードで実現できます。

public class AtomicBooleanSample {
    private AtomicBoolean locked = new AtomicBoolean(false);

    private void lock() {
        while(!this.locked.compareAndSet(false, true)) {
            //a thread will be locked here
        }
    }

    private void unlock() {
        this.locked.set(false);
    }
}

共有リソースの場合、最初のスレッドがlock()メソッドを実行すると、lockedインスタンス変数の値がに設定されます。これtrueは、期待値がの値と同じでlockedあり、共有リソースにアクセスするためのロックを取得するためです。

最初のスレッドがメソッドを呼び出す前unlock()に、別のスレッドがロックしようとすると、の値lockedが異なるために失敗し(true期待値を満たしていない)、最初のスレッドが値をfalsefalseに設定するまでループ内で実行されます。locked

于 2021-10-01T09:54:26.203 に答える
-1

CASアルゴリズムは、compareAndSet(false, true)成功するまで廃止されるため、競合の多い状況でパフォーマンスに影響を及ぼし ます。したがって、アトミック性が必要ない場合は、単純なブール値の方が適している可能性があります。

于 2013-01-25T08:27:35.307 に答える