CAS:什么是 CAS 机制?
cas目的是实现原子操作解释一下:
"原子操作(atomic operation)是不需要synchronized",这是多线程编程的老生常谈了。所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切 [1] 换到另一个线程)。 这是百度百科的解释
意思就是这个状态不会被中间态打断,例如银行转账机制,一个账号扣钱了,收钱账户也一定要收钱,不能中断
在java中原子操作 用于多线程的操作场景避免一个共享变量没有达到预期值
参见一个例子不安全场景:
这个结果 count不一定是200,因为存在多线程的竞争问题可能小于200,如果把run方法里面 加上synchronized代码块后每个线程的运行的状态不会受别的线程影响,实现了原子操作,最中结果一定是200.
java.util.concurrent.atomic包下 有一系列原子类
这中操作最后也是200,因为原子类专门解决了这个问题
java.util.concurrent.atomic 包下的类就是解决CAS的问题的,都是原子类。
原子类中的value 利用了volatile 实现的变量值共享。
,核心原理是:CAS机制当中使用了3个基本操作数:内存地址V,旧的预期值A,要修改的新值B。
每次更新的时候旧值都要与内存值比较,不一致会更新失败,然后利用内存值继续更新(出现了自旋操作,在高并发下比较危险会严重消耗cpu资源)
比如第二个线程运行到97的时候 第一个线程由于反应较慢才运行到5那么当5自增的时候一定会失败内存值与旧值不一致,所以进行自旋从97开始到98,第二个线程开始运行98旧值是97所以也会失败开始自旋到98,以此类推就实现了交替自增最终结果是200.
图文并茂的讲解。
cas是乐观锁,synchronized 是悲观锁, 在大并发下synchronized 的使用要比cas好些(CAS自旋的概率会比较大,从而浪费更多的CPU资),并发不大的时候cas性能好(不需要切换线程,操作自旋几率较少)
cas存在的问题:
ABA问题,如果 一个值是A, 被线程2变成了B, 被线程2或者其它的线程又给变回了A, 那么此时线程1操作的时候检查到的还是A,就认为没有变化,则执行更新,
AtomicStampedReference类解决了该问题,加入了版本号的解决方式。类似数据库的乐观锁加入版本号机制。
只能保证一个共享变量的原子操作,AtomicReference类能够满足多个变量的原子操作。