CAS算法
1、CAS概念:
CAS是CompareAndSwap的缩写,中文意思是:比较并替换。当要进行CAS操作时,先比较内存地址和原来预期的
地址比较,如果相同,表示这块内存地址没有被修改,可以用新地址替换,否则说明该地址被修改了,取消替换操作。
整个过程就是个原子操作。以线程为例,CAS算法先记录要修改地址的值,然后在修改时查看要修改的地址是否被
其他线程修改。然后根据情况决定进行哪种操作。
2、CAS应用:
1:在原子类变量中,如java.util.concurrent.atomic中的AtomicXXX,都使用了这些底层的JVM支持为数字类型的引用
类型提供一种高效的CAS操作,而在java.util.concurrent中的大多数类在实现时都直接或间接的使用了这些原子变量类。
2:CAS的原子操作可以用来实现乐观锁,当资源竞争程度不大的时候,不需要阻塞线程,这时候就可以通过CAS的
原子操作通过短暂的占用处理机来减少唤醒和切换线程的开销。
3、CAS缺点:
1、如果竞争资源程度比较大,或者同步竞争资源的线程比较多,此时不适合用CAS来实现乐观锁,因为不断的自旋(whie)
循环询问,这样会造成cpu的浪费。这时候应该采用synchronized来保证同步的准确性和减少cpu浪费。
2、可能产生ABA问题
加入有一个链表,头部是A,连接B
这时候线程a通过CAS操作把B放在链表的头部,首先记录了链表的头部A,在执行CAS操作之前,
另一个线程先把A,B出栈,然后push D,C,A,此时B处于游离态。
然后线程a回来发现栈顶是A,CAS操作成功。把B放在栈顶,实际上应该是BADC,而实际是:
B.next()为空,C D消失了。
从Java1.5开始JDK的atomic包里提供了一个类AtomicStampedReference来解决ABA问题。这个类的compareAndSet
方法作用是首先检查当前引用是否等于预期引用,并且当前标志是否等于预期标志,如果全部相等,则以原子方式将该
引用和该标志的值设置为给定的更新值。这也是我们上面图片所展示的。
3、当对一个共享变量执行操作时,我们可以使用循环CAS的方式来保证原子操作,但是对多个共享变量操作时,循环
CAS就无法保证操作的原子性,但是我们可以把多个共享变量放在一个类里,在jdk1.5中提供了AtomicReference类来
保证引用对象之间的原子性。
本文部分参考博客:Java并发问题–乐观锁与悲观锁以及乐观锁的一种实现方式-CAS