AtomicIntegerのgetAndIncrementはi ++と同等ですが、なぜ原子性を保証できるのですか?

このメソッドの基礎となるソースコードを研究する
ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入

AtomicIntegerはCASを使用しますが、同期する必要はありません

同期との整合性は保証されますが、並行性は大幅に低下し
ます。CASを使用してdo ... whileを使用し、一貫性を確保し、並行性を低下させないように繰り返し判断します。
CAS ---->コンペアアンドスワップ、彼はCPU同時実行プリミティブです。彼は実行プロセス中に中断されることは許可されていません。つまり、CASはCPUのアトミック命令であり、データの不整合を引き起こすことはありません。
CASのデメリット:
1。同時実行性の高い環境では、whileループを追加して判断に失敗すると、カップのコストが非常に大きくなります。
2.共有変数のアトミック性を保証するだけでは、コードの一部を保証することはできません。
3. ABA問題を引き起こす可能性があります
。4つの単語は、王子のためのジャコウネコを要約しています。
t1とt2が同時にデータAを操作する場合、t1はデータAをBに変更してメインメモリに更新しますが、t2はこの時点ではわかりません。t1はBをAに更新し、t2はメインに移動します。メモリから、Aはまだ大丈夫なので、メインメモリのAを彼自身のデータに変更しました。これはABA問題です

低水準アセンブリ言語
ここに画像の説明を挿入

ABA問題の解決策:

アトミッククラスには、バージョン番号でこの問題を解決できるAtomicStampedReferenceクラスがあります。

public class ABADemo {
    /**
     * 这里的Integer不能大于127若大于127则不会出现ABA情况,也就是没有CAS
     * true	128
     * false	128
     */
    private static AtomicReference<Integer> atomicReference = new AtomicReference<>(100);

    private static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100,1);

    public static void main(String[] args) {

        System.out.println("===以下是ABA问题的产生===");

        new Thread(() ->{
            System.out.println(atomicReference.compareAndSet(100, 127)+"\t"+atomicReference.get());

            System.out.println(atomicReference.compareAndSet(127, 100)+"\t"+atomicReference.get());

        },"t1").start();


        new Thread(() -> {

            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(atomicReference.compareAndSet(100, 2019)+"\t"+atomicReference.get());

        },"t2").start();

        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("===以下是ABA问题的解决===");

        new Thread(() ->{
            System.out.println(Thread.currentThread().getName()+"\t第一次版本号:"+atomicStampedReference.getStamp());
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(atomicStampedReference.compareAndSet(100, 127,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1)+"\t"+atomicStampedReference.getReference());

            System.out.println(Thread.currentThread().getName()+"\t第二次版本号:"+atomicStampedReference.getStamp());
            System.out.println(atomicStampedReference.compareAndSet(127, 100,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1)+"\t"+atomicStampedReference.getReference());

            System.out.println(Thread.currentThread().getName()+"\t第三次版本号:"+atomicStampedReference.getStamp());

        },"t3").start();


        new Thread(() -> {
            int stamp = atomicStampedReference.getStamp();

            System.out.println(Thread.currentThread().getName()+"\t第一次版本号:"+atomicStampedReference.getStamp());
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(atomicStampedReference.compareAndSet(100, 2019,stamp,stamp+1)+"\t"+atomicStampedReference.getReference());
            System.out.println(Thread.currentThread().getName()+"\t最新的版本号:"+atomicStampedReference.getStamp());



        },"t4").start();


    }
}

おすすめ

転載: blog.csdn.net/qq_36905956/article/details/105857254