CAS浅析

CAS
CAS是一种无锁算法,它通过CPU的CAS指令保证原子性。工作原理如下:CPU去更新一个值,但如果想改的值不再是原来的值,操作就失败,因为很明显,有其它操作先改变了这个值。举个例子:

有两个线程A和B同时取得内存的一个值number=10,他们会备份number到自己线程的内存工作空间。假设A和B都把number+1,这时线程A先把number=11写回到主内存。B线程比较主内存的值发现不是10了,这就知道了中间有线程修改了number,B线程就会从主存中获取当前最新的值,再次+1,由于中间没有其他线程修改number,所以线程B成功把number=12写入主存。示例图:
CAS浅析_第1张图片

CAS存在的问题

  • ABA:如果内存的值从A->B->A,线程做CAS的时候是不知道中间有线程修改了值,解决办法是在数值前面加入版本号,1A->2B->3A,这就发现问题了。JDK提供了AtomicStampedReference,在AtomicReference原子类的基础上提供了版本号控制,避免ABA问题。
  • CAS自旋消耗CPU较大:如果CAS操作长时间没有成功,java会自旋,再一次尝试。自旋是比较消耗CPU资源的操作。
  • 只能保证一个值的CAS操作(CPU级别):当对一个共享变量操作时,可以使用CAS。如果需要对多个变量操作,可以使用锁来解决。JDK提供了AtomicReference原子类,可以把多个变量封装成一个对象来保证原子性。

JDK提供了哪些依赖CAS的实现类
像AtomicInteger、AtomicReference、AtomicStampedReference这种Atomic开头的类都是基于CAS实现的。由于实现比较简单,不展开讨论了。

JDK有了synchronization,为什么还要CAS?
因为synchronization比较重,可能会导致线程挂起,线程的切换是非常消耗CPU资源的。CAS在简单的问题中显得非常好用,比如给一个整数+1操作,一个AtomicInteger类搞定。但是如果是复杂的问题,用synchronization实现起来会比较简单。

你可能感兴趣的:(CAS浅析)