JUC之CAS

本文乃个人拙见,如有错误,欢迎指出,不能误导新人

上一节讲到了volatile,知道了volatile的三个特性,并且知道了不具备原子性,那么怎么解决这个问题呢?
这个时候就引出了JUC下面的java.util.concurrent.atomic(原子)包,
在这里插入图片描述
在这个包里面我们看到了好多以Atomic开头的类,其中就有AtomicInteger,这个就是来保证原子性的一个类?我们来操作一下。如下图,可以看到使用AtomicInteger之后结果是20000,也就是说不存在原子操作割分的情况,那么为什么这个类是怎么实现的呢?这个时候就引出了我们的主题CAS。
在这里插入图片描述

CAS

点进incrementAndGet方法,如下图,可以看到里面是用unsafe类来实现的,那么问题来了,什么是unsafe类呢?这个问题留到后面再解决,我们直接点进getAndAddInt方法。
在这里插入图片描述
这里的第一个参数var1是要增加的那个int值,var2表示再内存的偏移量(这个偏移量是用来找到对象地址的),var4表示增加的值,var5 = this.getIntVolatile(var1, var2);这行代码表示找到内存中的值,接着,compareAndSwapInt方法表示,var1偏移var2之后的值和var5是否相等,相等就设置为var5+var4不相等就返回false,然后继续进入do循环,拿到对象值进行比较,反复循环,这种操作叫做自旋,而compareAndSwapInt这个方法首字母就叫做CAS,CAS是一种思想,比较并交换,compareandswap,也可以叫做compareandset,那么问题来了,compareAndSwapInt()这个方法是不是具有原子性呢,这个方法是unsafe类中调用的,这个方法是调用的java native interface来实现的(JNI),就是java可以调用本地的方法,调用C来操作CPU指令来完成操作,而cpu指令中的这段代码是加上lock锁了的,所以CAS操作具有原子性。所以使用原子类就可以将volatile的原子性的问题解决了。
在这里插入图片描述

思考

volatile是轻量级的锁,使用CAS实现原子性,来达到和synchronized的功能,主要思想还是读数据和写数据的分离,在一般的业务中读数据占了整个数据操作的绝大部分,而这个时候因为要兼顾写操作所以使用synchornized,而synchornized会把读写都锁上,这个时候就出现了volatile,可见性的存在是的读操作的时候不去加锁,再少量写操作的时候进行CAS操作,但是当这种写操作的比例变大的时候,就是要进行频繁的CAS,而这个时候只有一个能CAS,其他的都要等待,就会不停的自旋,消耗很多资源,所以如果自旋的次数很多的时候可以进行锁住,这就是1.6之后的synchronized优化,在自旋了一次之后进行加锁,当然根据读数据与写数据的比例,可以对自旋的次数进行平衡取舍,这大概就是CAS思想了吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小丸子呢

致力于源码分析,期待您的激励

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

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

打赏作者

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

抵扣说明:

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

余额充值