深入理解CAS、unsafe类和ABA问题解决

理解CAS

一、理解CAS是什么
之前学习的原子类的底层用的就是CAS,是compareAndSet的缩写,比较并交换的意思

二、使用方法

public class CasTest {
    public static void main(String[] args) {
        //创建integer的原子类,设置默认值是200
        AtomicInteger atomicInteger = new AtomicInteger(200);
        //比较并交换,如果是期望的值,那么就更新成新的数据。如果atomicInteger中的值是200,更新成201
        atomicInteger.compareAndSet(200,201);

        System.out.println(atomicInteger.get());
    }
}

控制台打印结果:


三、CAS的缺点
1、底层调用自旋锁会循环耗时
2、一次性只能保证一个共享变量的原子性
3、ABA问题

理解unsafe类

一、学习Volatile认识和三大特性中,涉及到了一个原子类中的方法getAndIncrement(),相当与常规代码中的++自增,分析这个方法的底层,是用到了unsafe类

这里也用到了一个底层的CAS:比较当前工作内存中的值和主内存中的值,如果这个值是期望的,那么执行操作,如果不是就一直循环,因为这里用到了一个自旋锁

unsafe类:首先需要了解到Java是无法直接操作内存的,因此在和内存交互的时候就用到了native关键字,
        调用本地方法库中的方法,调用C++来操作内存
        而unsafe类是Java留的一个后门,我们也可以通过这个类来操作内存!

原子引用解决ABA问题

一、什么是ABA问题
A和B同时拿到了主存中相同的数据,B线程以很快的时间对数据进行了修改,并且又以很快的速度还原回了原来的数据,那么此时A线程却不知情主存中的数据发生了修改,所以A线程还是照旧执行他的任务,没有任何的反应

二、原子引用解决ABA问题
通俗的将就是带版本号的原子操作
涉及到了一个原子操作类,atomicStampedReference原子引用类(乐观锁机制),里面有获取版本号的方法

代码如下:

public class casDemo01 {
    public static void main(String[] args) {
        //创建带版本号的数据
        AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<Integer>(1,1);

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

            //模拟延时
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //如果期望的值是1,修改成2,更新版本号在原有基础上+1
            System.out.println(atomicStampedReference.compareAndSet(1, 2, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1));
            System.out.println("A2-->" + atomicStampedReference.getStamp());

            //将线程A更新的数据修改回原来的数据
            System.out.println(atomicStampedReference.compareAndSet(2, 1, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1));
            System.out.println("A3-->" + atomicStampedReference.getStamp());
        },"A").start();

        new Thread(()->{
            int stamp2 = atomicStampedReference.getStamp();
            System.out.println("B1-->" + stamp2);
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(atomicStampedReference.compareAndSet(1, 6, stamp2, stamp2 + 1));
            System.out.println("B1-->" + atomicStampedReference.getStamp());
        },"B").start();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Be explorer

若认可笔者文章,手头富裕望支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值