CAS知道吗?如何实现的?

一、概念

CAS—compareAndSet字面意思:比较并交互
真实值和期望值相同,执行修改,否则不执行。

CAS方法存在于UnSafe类中,UnSafe可以直接操作系统内存资源。

CAS是一种系统原语,属于操作系统用语,是有若干条连续不可中断的指令构成的,也就是说,CAS是一条CPU的原子指令

二、源码阅读示例

我们以UnSafe的getAndSetInt方法为例
这个方法的作用是,获得并且设置一个int值,返回获得的结果

public final int getAndSetInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var4));

        return var5;
    }

首先这个方法接收4个参数,第一个为对象,第二个是内存地址偏移量,我们通过这两个参数,直接从内存中获得我们需要的操作数var5
while里的判断条件,就是一个本地的CAS方法,比较并交换int值

public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

这是个返回boolean的方法,意思是:如果期望值和实际值相等,则交换,返回true,否则返回false。这个方法以在cpu级别保证了原子性,不会发生数据不一致问题。

再回到上面的循环,如果CAS交换成功,返回true,那么循环条件整体为false,退出循环,返回更新之前的操作数,如果CAS交换失败,那么则会一直重复这个do-while循环,不停的取值,尝试比较并交换。我们把它称之为自旋

三、ABA问题和原子引用

ABA故名思意,A变成了B又变成了A,从结果上看,A并没有改变,但实际上是A改变了多次。
以CAS的机制是不能意识到变量是改变了多次的。

JUC提供了AtomicStampedReference,即带戳的原子引用类,可以理解为有版本号的原子引用

AtomicStampedReference<Integer> asr = new AtomicStampedReference<>(100,1)

通过版本号,解决ABA的问题,这样引用和预期相同,版本号却和预期不相通,不能执行CAS操作

boolean res = asr.compareAndSet(exceptref, newref,exceptstamp,newstamp);

四、小总结

CAS是CPU级别的原子指令,保证了数据一致性
CAS提升了并发效率,也增大了CPU开销(因为一直自旋的原因)
CAS只能保证一个共享变量的原子性
CAS存在ABA的问题,可以使用AtomicStampedReference类来解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值