JUC —— 深入理解CAS

CAS

compareAndSet 比较并交换

public class CASTest {
    public static void main(String[] args) {
        AtomicInteger atomicInteger = new AtomicInteger(2020);
        //期望、更新
        // public final boolean compareAndSet(int expect, int update)
        //如果我的期望值达到了,就更新;没达到,就不更新
        System.out.println(atomicInteger.compareAndSet(2020, 2021));
        System.out.println(atomicInteger.get());

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

测试结果:

true
2021
false
2021

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

  • 循环会耗时
  • 一次性只能保证一个共享变量的原子性
  • ABA问题

ABA问题: 就是两个线程要操作主存中的一个变量,主存中有一个num = 0;线程一期望num=0,修改为1,但在线程一拿到主存的num之前,线程二先拿到了主存中的数据,线程二做了两个操作,先是期望num=0,修改为3,然后又把num改回了0。这个时候线程1来拿主存中的num,发现num=0,符合他的预期,就进行了修改,但是他并不知道这个num = 0已经被别人动过了,不是最开始的0了,是经过别人修改后返回的0。

怎么解决ABA问题呢? 原子引用

原子引用

public class ABATest {
    public static void main(String[] args) {
        AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<Integer>(1,1);
        int stamp = atomicStampedReference.getStamp();
        System.out.println("初始时间戳"+stamp);
        new Thread(()->{
            System.out.println("a首次获取时间戳"+atomicStampedReference.getStamp());

            System.out.println(atomicStampedReference.compareAndSet(1, 2, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1));

            System.out.println("a操作一次时间戳"+atomicStampedReference.getStamp());
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(atomicStampedReference.compareAndSet(2, 1, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1));
            System.out.println("a操作二次时间戳"+atomicStampedReference.getStamp());
        },"a").start();

        new Thread(()->{
            System.out.println(atomicStampedReference.compareAndSet(1, 6, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1));

            System.out.println("b操作一次时间戳"+atomicStampedReference.getStamp());
        },"b").start();
    }
}

执行结果:

初始时间戳1
a首次获取时间戳1
true
a操作一次时间戳2
false
b操作一次时间戳2
true
a操作二次时间戳3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值