javaプログラミングCASの理解


1.ASとは何ですか
CASとはCompre and Swapという意味です。比較して交換するという意味です。CASは3つの値を使いました。Vメモリ値、A予想値、Bが更新する値を使って、メモリ値が予想値に等しいかどうかを判断します。等しいとBをメモリ値に更新します。Javaでは、Unisafe類を使ってCASを実現します。
2.CAS実現
  
   public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }
AtomicInteger類を例にとると、メソッドget AndIncrementがあり、unsafeのget AndAddIntメソッドを呼び出し、thisは現在のオブジェクトであり、valueOffsetはvalueのメモリアドレスである。
  public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

        return var5;
    }
Usafe類get AndAddInt方法では、var 1は転送されたAtomicIntegerの対象であり、var 2はその対象のアドレスであり、var 4は操作の値であり、var 5はメモリ値であり、var 1とvar 2を通じてメモリから取得され、メモリ値はvolatileによって修飾されているので、スレッドが見られます。this.compareAndSwapInt(var1, var2, var5, var5 + var4)を実行し、スレッドがAtomicIntegerの値を修正していない場合、var 1とvar 2で取得した値がvar 5と等しい場合、AtomicIntegerのvalue値を更新し、trueに戻り、ループを終了する。スレッドがAtomicIntegerの値を修正すると、var 1とvar 2で取得した値はvar 5と等しくなく、falseに戻り、次のループを行い、再びdo whileループに入ると、var5 = this.getIntVolatile(var1, var2);方法でメモリ値を更新し、this.compareAndSwapInt(var1, var2, var5, var5 + var4)を実行し、もしスレッドがAtomicIntegerの値を修正していないなら、var 1とvar 2で取得した値はvar 5と等しい。AtomicIntegerのvalue値を更新し、trueに戻り、ループを終了します。上記の過程は原子操作を実現した。
3.CASに存在する問題
1.A B A問題CASは操作値の時に値が変化しているかどうかを確認して、変化がなければ更新しますが、もし一つの値がもとはAで、Bになったら、またAになります。CASを使って検査すると、その値が変化していないことが分かりますが、実際には変化しました。これはCASのABA問題です。よくある解決策はバージョン番号を使うことです。変数の前にバージョン番号を追加し、変数が更新されるごとにバージョン番号を加算すると、A-B-Aは1 A-2 B-3 Aとなります。JDKは1.5からAtomicStopedereferenceクラスを提供してABA問題を解決します。このクラスのcompreAndSet方法の役割は、現在の参照が参照に等しいかどうかを最初にチェックし、現在のフラグが予定されているフラグに等しいかどうかを確認することであり、すべて等しい場合、原子的にこの参照とマークの値を所定の更新値に設定することである。
2.サイクル時間が長いとオーバーヘッドが大きい上で、CASが成功しないと元のスピン(ずっとdo while)になると言っていましたが、長時間スピンがCPUに大きな実行オーバーヘッドをもたらします。
3.一つの共有変数の原子操作だけが一つの共有変数に対して操作を行う場合、CASは原子操作を保証することができますが、複数の共有変数を操作する場合、CASは動作の原子性を保証することができません。