java中你所不知道的CAS操作
1.CAS是什么
Compare and Swap(比较并操作),由处理器架构支持,语义是如果当前值V和旧值A相同,则将当前值修改为B,如果不相同则不修改。CAS操作采用的是乐观锁技术,当多线程同时修改某个变量时只有一个成功,其他线程会失败当是不会被挂起,会被告知失败并重试。
2.CAS操作和synchronized有什么区别呢
synchronized关键字采用悲观锁技术,线程独享锁,其他线程会被挂起知道锁被释放线程恢复,挂起和恢复会有很大的开销。
3.java中CAS操作有哪些
java1.5之后引入了对CAS操作的底层支持,比如在intel的CPU中使用的是cmpxchg指令。java.util.concurrent.atomic中的AtomicXXX都使用了CAS操作,比如AtomicInteger的getAndIncrement方法来实现i++的原子的复合操作。举例说明实现一个无锁数据结构(非阻塞算法):
实现一个单链表栈,栈顶A,A.next为B,需要将A出栈。两个线程同时操作head.compareAndSwap(A,B),线程T1比较栈顶的当前值和旧值均为A则将A改为B,线程T2看到栈顶的当前值为B和旧值A不同则什么都不做。这就实现了无锁的堆栈。
4.ABA问题的解决方案
无锁的数据结构中存在一个ABA的问题,如果线程T1经过一系列的操作后将栈变为A->C->D,那么T2经过比较后仍然会将栈变为B,会将C和D丢失掉。
解决ABA问题的某些算法中会记录数据变换的过程,可以通过一个版本号来记录,A变成B再变成A和没有任何操作是的版本号是不同的。
java中AtomicStampedReference和AtomicMarkableReference实现了解决ABA的问题。AtomicStampedReference会使用一个Pair来保存引用和计数器。每次操作前不但会比较引用值还会比较计数器值,完成操作后会更新计数器的值。AtomicMarkableReference使用Pair来保存引用和布尔类型的标记值。AtomicStampedReference可查看引用的改变次数,AtomicMarkableReference只关心有没改变