CAS分析

CAS:Compare and Swap, 翻译成比较并交换。html

 
CAS 指的是现代 CPU 普遍支持的一种对内存中的共享数据进行操做的一种特殊指令。这个指令会对内存中的共享数据作原子的读写操做。 简单介绍一下这个指令的操做过程:首先,CPU 会将内存中将要被更改的数据与指望的值作比较。而后,当这两个值相等时,CPU 才会将内存中的数值替换为新的值。不然便不作操做。最后,CPU 会将旧的数值返回。这一系列的操做是原子的。它们虽然看似复杂,但倒是 Java 5 并发机制优于原有锁机制的根本。简单来讲,CAS 的含义是“我认为原有的值应该是什么,若是是,则将原有的值更新为新值,不然不作修改,并告诉我原来的值是多少”。(这段描述引自《Java并发编程实践》)

简单的来讲,CAS有3个操做数,内存值V,旧的预期值A,要修改的新值B。 当且仅当预期值A和内存值V相同时,将内存值V修改成B,不然返回V。这是一种乐观锁的思路,它相信在它修改以前,没有其它线程去修改它;而 Synchronized是一种悲观锁,它认为在它修改以前,必定会有其它线程去修改它,悲观锁效率很低
 
CAS优势
高效解决原子操做
 
CAS缺点
CAS虽然很高效的解决原子操做,可是CAS仍然存在三大问题。ABA问题,循环时间长开销大和只能保证一个共享变量的原子操做

1.  ABA问题。由于CAS须要在操做值的时候检查下值有没有发生变化,若是没有发生变化则更新,可是若是一个值原来是A,变成了B,又变成了A,那么使用CAS进行检查时会发现它的值没有发生变化,可是实际上却变化了。ABA问题的解决思路就是使用版本号。在变量前面追加上版本号,每次变量更新的时候把版本号加一,那么A-B-A 就会变成1A-2B-3A。编程

从Java1.5开始JDK的atomic包里提供了一个类AtomicStampedReference来解决ABA问题。这个类的compareAndSet方法做用是首先检查当前引用是否等于预期引用,而且当前标志是否等于预期标志,若是所有相等,则以原子方式将该引用和该标志的值设置为给定的更新值。并发

关于ABA问题参考文档: http://blog.hesey.net/2011/09/resolve-aba-by-atomicstampedreference.htmlatom

2. 循环时间长开销大。自旋CAS若是长时间不成功,会给CPU带来很是大的执行开销。若是JVM能支持处理器提供的pause指令那么效率会有必定的提高,pause指令有两个做用,第一它能够延迟流水线执行指令(de-pipeline),使CPU不会消耗过多的执行资源,延迟的时间取决于具体实现的版本,在一些处理器上延迟时间是零。第二它能够避免在退出循环的时候因内存顺序冲突(memory order violation)而引发CPU流水线被清空(CPU pipeline flush),从而提升CPU的执行效率。spa

 3. 只能保证一个共享变量的原子操做。当对一个共享变量执行操做时,咱们可使用循环CAS的方式来保证原子操做,可是对多个共享变量操做时,循环CAS就没法保证操做的原子性,这个时候就能够用锁,或者有一个取巧的办法,就是把多个共享变量合并成一个共享变量来操做。好比有两个共享变量i=2,j=a,合并一下ij=2a,而后用CAS来操做ij。从Java1.5开始JDK提供了AtomicReference类来保证引用对象之间的原子性,你能够把多个变量放在一个对象里来进行CAS操做。.net

相关文章
相关标签/搜索