JUC(10)深入理解CAS和ABA

1、CAS

在这里插入图片描述

在这里插入图片描述

package com.cas;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * CAS compareAndSet:比较并交换
 */
public class CASDemo {
    public static void main(String[] args) {
        AtomicInteger atomicInteger = new AtomicInteger(2021);
        /**
         * 期望、更新
         * public final boolean compareAndSet(int expect, int update)
         * 如果期望值达到了,那么就更新,否则,就不更新
         */
        atomicInteger.compareAndSet(2021,2022);
        System.out.println(atomicInteger.get());
    }
}

CAS:比较当前工作内存中的值和主存中的值,如果这个值是期望的,那么执行操作!如果不是、一直循环

缺点:

  • 1、循环会耗时
  • 2、一次性只能保证一个共享变量的原子性
  • 3、存在ABA问题
    ABA问题:狸猫换太子

举例子:A 打算让1变为2.在这个过程中,线程B已经对其进行过修改,从1,到3,再从3,到1。对线程A来讲,好像没啥大的变化。
在这里插入图片描述

package com.cas;

import java.util.concurrent.atomic.AtomicInteger;

public class ABADemo {
    public static void main(String[] args) {
        AtomicInteger atomicInteger = new AtomicInteger(2021);
        /**
         * 期望、更新
         * public final boolean compareAndSet(int expect, int update)
         * 如果期望值达到了,那么就更新,否则,就不更新
         */
        System.out.println(atomicInteger.compareAndSet(2021, 2022));
        System.out.println(atomicInteger.get());

        System.out.println(atomicInteger.compareAndSet(2022, 2021));
        System.out.println(atomicInteger.get());

        System.out.println(atomicInteger.compareAndSet(2021, 6666));
        System.out.println(atomicInteger.get());

    }
}

2、原子引用解决ABA问题,版本号。修改后,可以看到

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

举例子(乐观锁)

package com.cas;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * AtomicStampedReference 注意:如果泛型是一个包装类,注意对象的引用问题
 */
public class AtomicStampedReferenceDemo {
    public static void main(String[] args) {
        AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(66, 1);

        new Thread(()->{
         int stamp = atomicStampedReference.getStamp();//获得版本号
         System.out.println("A===>"+stamp);



            atomicStampedReference.compareAndSet(66,99,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1);
            System.out.println("A2==>"+atomicStampedReference.getStamp());

            atomicStampedReference.compareAndSet(99,66,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1);
            System.out.println("A3==>"+atomicStampedReference.getStamp());

        },"A").start();

        new Thread(()->{
            int stamp = atomicStampedReference.getStamp();//获得版本号
            System.out.println("B===>"+stamp);

            try {
                TimeUnit.SECONDS.sleep(6);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            atomicStampedReference.compareAndSet(66,6,stamp,stamp+1);
            System.out.println("B1==>"+atomicStampedReference.getStamp());

        },"B").start();
    }
}

测试结果
在这里插入图片描述

posted on 2022-08-28 22:18  热爱技术的小郑  阅读(54)  评论(0编辑  收藏  举报