javaの - CASとCAS基本原理

それは何CAS?

  フルネームのCASは、それがCPUの同時実行プリミティブ、すなわち、ハードウェアレベルで比較交換、CPUが新しい比較値を設定するか否かを判断し、この操作は、自然の中でアトミックである、それは他のスレッドによって中断されることはありません。CAS Mansianメカニズムが同時コンピューティングを避けるためにするときJAVAと下部は、java.util.concurrent.atomic原因データで契約が使用されています。

アトミック基本となる実装

各カテゴリの下に主に操作-そしてスワップ比較するためには、java.util.concurrent.atomic危険なクラスを使用しています。
Javaで安全でない基本となるクラス、このような配列操作などの多くの基本的な操作、オブジェクトの操作、メモリ動作を含み、CAS動作、スレッド(パーク)動作、フェンス(フェンス)操作、JUCパッケージ、三者枠組みの一部は、安全でないクラスを使用安全性を確保するために、同時。JDKソース内の複数のクラスの危険なクラスは、その実装に基づいて、このクラスのJVM、バイパスへのより低レベルの機能の一部を提供するために使用効率を向上させることができます。しかし、それは両刃の剣である:その名がそれを示しているように、それは危険であり、それは手動で空きメモリを割り当てるために必要なもの(GCを回復することはありません)。安全でないクラスは、JNI特定の機能への簡単な代替手段を提供します。同時に、物事が容易になり、効率性を確保します。
あなたがここAtomicReferenceが提供するジェネリッククラスによって参照することができる原子をカスタマイズする必要がある場合、これはあまりにも多くの導入ではありません。
開始点としてのAtomicIntegerクラスの隣には、アトミック並行処理の安全性を確保するために比較交換を使用したかを確認します。

public class AtomicInteger extends Number implements java.io.Serializable {
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long valueOffset;
    //1.objectFieldOffset()方法用于获取某个字段相对Java对象的起始地址的偏移量。
    //2.下次访问将直接通过this对象与相对偏移量直接从内存访问value的值。从不经过JVM虚拟机。
    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }
    private volatile int value;
    
    .
    .
    .
    //调用unsafe对预期值进行判断,如果判断成功则将值设置进去。
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }
    //调用unsafe.getAndAddInt方法,该方法内部采用自旋锁不断compareAndSet当设置成功后才跳循环,否则不断得查询并且计算然后进行compareAndSet。
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }
public final class Unsafe {
    .
    .
    .
    public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);
    public native int getIntVolatile(Object var1, long var2);
    //通过一个死循环不停的获取值并且计算然后比较是否能够设置否则继续如此操作。
    public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        //compareAndSwapInt是Unsafe类利用计算机底层实现的,该操作是具有原子性,所以不必担心并发问题。
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
        return var5;
    }
}

CASの欠点

CASは、ロックにウェイトロック解除状態では全体の方法、他のスレッドが同期されていませんので。そのため、CASは、並行性が向上します。しかし、同時実行の強化で、同時にいくつかの欠点を伴うことになります。

  1. 長いサイクルタイム、CPUのオーバーヘッドが増加します。
  2. アトミック操作は、共有変数を保証することができます。
  3. ABAは、問題が生じます。

ABAの問題

その初期値が1であるような変数があると、2つのスレッドが、スレッドAおよびスレッドBであり、呼び出したスレッドサイクルははるかに低いスレッドBよりなります

オーダー スレッド スレッドB
1 A = getIntVolatile(0)
2 A = getIntVolatile(0)
3 this.compareAndSwapInt(VAR1、VAR2、1)
4 A = getIntVolatile(1)
5 this.compareAndSwapInt(VAR1、VAR2、0)
6 this.compareAndSwapInt(VAR1、VAR2、2)

スレッドBのための可能compareAndSwapIntが成功し、彼が感じるスレッドAが値内部を設定することができる期待値compareAndSwapIntに沿って実行する時間限り、1変数、次いで0プロセスに設定され、結果のみに関するスレッドBであろうことはできませんです。

ABA問題解決

ABAは、アイデアは、バージョン管理を導入することでその問題を解決します。バージョン番号は1ずつインクリメントされるのcompareAndSetのあらゆる成功した行為について、そしてそれぞれが、それはABAの問題を回避することができるようにバージョン番号が、試合の予想を行いました。幸いなことに、同じは、java.util.concurrent.atomicパッケージで私たちに参照アトミックアクションクラスAtomicStampedReferenceに基づいて、バージョン番号を約束されています。

//创建出AtomicStampedReference实例,参数分别为初始值和初始版本号
AtomicStampedReference<Integer> atomicStampedReference=new AtomicStampedReference(100,1);
//获取当前版本号
int stamp=atomicStampedReference.getStamp();
//执行比较并且设置参数分别为期望值,设置新值,期望版本号,设置新版本号
atomicStampedReference.compareAndSet(100,200,stamp,stamp+1)

おすすめ

転載: www.cnblogs.com/cjunn/p/12231383.html