-
什么是CAS
cas全称为compareAndSwap,可以很清楚的翻译知道意思为“比较和交换”,字面意思其实就已经解释了CAS的实现原理 -
CAS简介
从jdk5开始,jdk提供了java.util.concurrent.*,此包下面的类在高并发场景下经常使用,包中的原子类基于CAS实现了区别于syncchrnoized同步锁,CAS是一种乐观锁 -
CAS实现原理解析
上图为cas实现的原理图,很好的诠释了CAS的名称“比较和交换”,先读取当前值,计算应该的结果,再读取值和旧值判断是否相同,如果相同则更新为新的值,如果不同则重复上诉步骤至完成
- 上诉步骤可能会出现ABA的问题,所谓ABA问题是指,第一次读取当前值是如果值为A,计算出结果值V后,再次读取值和A进行比较,发现值仍为A,但实际上此A非彼A,在计算过程中,其他线程可能已经将A更新过变为了B,但是又被其他线程更新回了A,虽然数值上均为A,但是实际意义可能已经发生过变化
- 如果对于ABA问题不需要特殊关注的场景情况下,这种问题可以忽略,但是如果需要特殊关注ABA问题的出现的话,需要采用其他方式判断此A是否为彼A,解决这种问题我们可以采用增加一个数值来表示当前值的版本号,在更新当前值的时候同时对版本号进行增加,在比较当前值和旧值是否相同的时候同时比较版本号是否相同即可解决此问题
- 有的同学可能会问,如果我在写入的时候数值被其他线程修改还是不能保证并发情况下数据一致性问题,其实此时就涉及到了CAS的底层源码实现,此问题后续会讲到jdk底层调用C++的实现
- CAS底层源码分析
以AtomicInteger实现原理为例
java.util.concurrent.atomic包下的原子类的实现经常被人们称为“自旋锁”或“无锁”
我们通过new AtomicInteger()后调用其incrementAndGet()方法来查看内部方法实现
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rmJfVNwH-1615791004639)(http://blog.cwcenter.top/upload/2021/03/image-6039b8d94dc9474daaff013d012a4fb6.png)]
可以看到AtomicInteger.incrementAndGet()方法的实现调用了Unsafe.class的getAndAddInt()方法实现,Unsafe.class是jdk提供的不安全操作类,里面封装了和操作系统打交道的一些方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-36GOikIU-1615791004654)(http://blog.cwcenter.top/upload/2021/03/image-0df8a82a4caf435d8a399d44751cf663.png)]
在Unsafe.class中,getAndAddInt实现是通过do while 实现,compareAndSwapInt为调用C++代码实现比较和交换的功能,具体C++代码不做详细说明,在C++代码中使用了汇编语言实现
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iyn2x8yp-1615791004657)(http://blog.cwcenter.top/upload/2021/03/image-af82d7bd9e6846528e642728267c688c.png)]
可以看到,汇编中有LOCK_IF,此判断是判断服务器cpu数量,如果是1个cpu则不进行加锁,如果是多个CPU则进行加锁操作,可以保证同时只有一个CPU对值进行更改,从而保证并发的数据一致性
小短腿的个人公众号上线啦,后续技术分享将优先在公众号进行哈,大家可以关注公众号,小短腿有什么新的分享会及时同步哈