本文转载自微信公众号“KK架构师”,作者wangkai。转载请联系KKarchitects公众号。一、CAS简介CAS的意思是compareandswap,比较和交换。CAS的示意图如下:比如一个很简单的操作,给变量A=2加1,结果为3。然后读取A的当前值E为2,计算内存中的结果V为3,并比较之前读出的A的当前值2和最新值,如果最新值为2,说明这个值没有被别人改过,那么就可以放心的把最终值更新为3了。有一种情况,在你更新结果之前,中间有另一个线程将A更新为5,然后再更新回2。但是从当前线程来看,并没有改变。这就是ABA问题。2、CAS的实现在java中,原子类都是用cas实现的,我们可以看一下源码。publicfinalintgetAndIncrement(){returnunsafe.getAndAddInt(this,valueOffset,1);}发现调用了unsafe类的getAndAddInt,继续看这个方法:publicfinalintgetAndAddInt(Objectvar1,longvar2,intvar4){intvar5;do{var5=this.getIntVolatile(var1,var2);}while(!this.compareAndSwapInt(var1,var2,var5,var5+var4));returnvar5;}这里是一个while循环,直到比较成功,看看这个compareAndSwapInt方法publicfinalnativebooleancompareAndSwapInt(Objectvar1,longvar2,intvar4,intvar5);发现这是一个native方法,也就是说是用c或者c++写的虚拟机的实现。在网上找到了HotSpot虚拟机的源码,找了一些资料,找到了这个compareAndSwapInt的c++代码:在unsafe.cpp文件的Unsafe_CompareAndSwapInt方法中,发现最后调用了Atomic::cmpxchg方法,然后我们发现atomic_linux_x86.inline.hpp文件里有一句LOCK_IF_MP(%4)"cmpxchgl%1,(%3)"LOCK_IF_MP是一个宏。这个宏的定义是:mp的意思是multiprocessor,也就是说需要锁定在multi-corecpu这个指令上。至此,结论就是最终调用了一条汇编指令:lockcmpxchg指令,实现了底层的cas。即cpu中有一条cmpxchg指令。但是这个指令不是原子的,就是取出来和比较是两个操作,中间有可能被别人打断。所以这个过程需要加锁,就是说我在操作这段内存的过程中不允许被别人打断。可以简单理解为锁定内存总线,其他人不可以修改这块内存。3、ABA问题的解法很简单。可以给数据加一个版本号,改一次就加一个新的版本号。在Java中,可以使用AtomicStampedReference来解决这个问题compareAndSet(100,101);atomicInt.compareAndSet(101,100);System.out.println("newvalue="+atomicInt.get());booleanresult1=atomicInt.compareAndSet(100,101);System.out.println(result1);//结果:trueAtomicIntegerv1=newAtomicInteger(100);AtomicIntegerv2=newAtomicInteger(101);AtomicStampedReference
