在运用CAS做Lock-Free操作中有一个经典的ABA问题:
线程1准备用CAS将变量的值由A替换为B,在此之前,线程2将变量的值由A替换为C,又由C替换为A,然后线程1执行CAS时发现变量的值仍然为A,所以CAS成功。但实际上这时的现场已经和最初不同了,尽管CAS成功,但可能存在潜藏的问题,例如下面的例子:
现有一个用单向链表实现的堆栈,栈顶为A,这时线程T1已经知道A.next为B,然后希望用CAS将栈顶替换为B:
head.compareAndSet(A,B);
在T1执行上面这条指令之前,线程T2介入,将A、B出栈,再pushD、C、A,此时堆栈结构如下图,而对象B此时处于游离状态:
此时轮到线程T1执行CAS操作,检测发现栈顶仍为A,所以CAS成功,栈顶变为B,但实际上B.next为null,所以此时的情况变为:
其中堆栈中只有B一个元素,C和D组成的链表不再存在于堆栈中,平白无故就把C、D丢掉了。
以上就是由于ABA问题带来的隐患,各种乐观锁的实现中通常都会用版本戳version来对记录或对象标记,避免并发操作带来的问题,在Java中,AtomicStampedReference<E>也实现了这个作用,它通过包装[E,Integer]的元组来对对象标记版本戳stamp,从而避免ABA问题,例如下面的代码分别用AtomicInteger和AtomicStampedReference来对初始值为100的原子整型变量进行更新,AtomicInteger会成功执行CAS操作,而加上版本戳的AtomicStampedReference对于ABA问题会执行CAS失败:
import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicStampedReference; public class ABA { private static AtomicInteger atomicInt = new AtomicInteger(100); private static AtomicStampedReference atomicStampedRef = new AtomicStampedReference(100, 0); public static void main(String[] args) throws InterruptedException { Thread intT1 = new Thread(new Runnable() { @Override public void run() { atomicInt.compareAndSet(100, 101); atomicInt.compareAndSet(101, 100); } }); Thread intT2 = new Thread(new Runnable() { @Override public void run() { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { } boolean c3 = atomicInt.compareAndSet(100, 101); System.out.println(c3); // true } }); intT1.start(); intT2.start(); intT1.join(); intT2.join(); Thread refT1 = new Thread(new Runnable() { @Override public void run() { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { } atomicStampedRef.compareAndSet(100, 101, atomicStampedRef.getStamp(), atomicStampedRef.getStamp() + 1); atomicStampedRef.compareAndSet(101, 100, atomicStampedRef.getStamp(), atomicStampedRef.getStamp() + 1); } }); Thread refT2 = new Thread(new Runnable() { @Override public void run() { int stamp = atomicStampedRef.getStamp(); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { } boolean c3 = atomicStampedRef.compareAndSet(100, 101, stamp, stamp + 1); System.out.println(c3); // false } }); refT1.start(); refT2.start(); } }
相关推荐
cas带来一个ABA问题 什么是ABA呢? 就是俩个线程同事操作,有可能有一个线程已经处理结束,那么第一个线程中间又一次fail操作,会在这个结果上在进行计算 t1 t2 A A->B->A A->C 那我们来看下维基百科上面的形象描述: 你...
• select&set业务场景,在并发时会出现一致性问题 • 基于“值”的CAS乐观锁,可能导致ABA问题 • CAS乐观锁,必须保证修改时的“此数据”就是“彼数据”,应该由“值”比对,优化为“版本号”比对
ABA专题:自闭症儿童ABA实操流程解析.doc
ABa格式.docABa格式.docABa格式.docABa格式.doc
ABA FS E001 Sale Item
AtomicStampedReference和ABA问题的解决 集合类不安全问题 List CopyOnWriteArrayList Set HashSet和HashMap Map Java锁 公平锁/非公平锁 可重入锁/递归锁 锁的配对 自旋锁 读写锁/独占/共享锁 Synchronized和Lock的...
主要介绍了浅谈Java中ABA问题及避免,具有一定借鉴价值,需要的朋友可以参考下
```AtomicStampedReference```来解决ABA问题,类中的```compareAndSet```方法作用首先检查当前引用是否等于预期引用,并且当前标志是否等于预期标志,如果相等,以原子方式将该引用和标记的值设置为给定的更新值。
ABA生理功能与信号转导相关综
亚高温强光胁迫下外源ABA对番茄叶片光合作用的影响,刘玉凤,刚爽,本文研究了亚高温强光胁迫下外源ABA对番茄叶片光合作用、PSI和PSII、抗氧化系统、ABA相关基因表达的影响。亚高温强光导致净光合速率�
SAMSUNG mcp flash: K5N5629ABA-AD11_RC_256128MB
单级ABA52563射频放大,和PE4302程控衰减,实测在1GHz以下可实现20dB左右增益,高于1GHz没有条件测试,内含原理图和PCB源文件
两级ABA52563级联放大,可实现小信号20dB以上增益,PE4302实现0~31.5dB信号衰减
ABA训练的基本原则和方法.pdf
CAS(Compare And Swap)是一种无锁算法。CAS算法是乐观锁的一种实现。CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当预期值A和内存值V相同时,将内存值V修改为B并返回true,否则返回false。
CAS(比较并交换)一个小demo import java.util.concurrent.atomic.AtomicInteger; public class CasDemo { public static void main(String[] args) { //默认初始值为5,也就是主存中的值为5 ...
NO参与水分胁迫下ABA维持玉米初生根生长,李晶,蒋明义,本实验以玉米(Zea mays L.)杂交种“农大108”为材料,以PEG-6000(25%)模拟低水势,发现在低水势下,经ABA抑制剂fluridone(FLU)(10μM )�
氮素对小麦叶片NO与ABA关系的影响及其对气孔行为的调控,张绪成,上官周平,在大田条件下,对不同氮素处理冬小麦(Triticum aestivum L.)分蘖期叶片气孔导度(Gs)、根叶脱落酸(ABA)含量和叶片一氧化氮(NO)含量进行了测...
NaCl胁迫对番茄嫁接苗叶片ABA和多胺含量的影响,陈淑芳,朱月林,以未经NaCl胁迫的番茄自根苗为对照,研究了100 mmol•L-1 NaCl胁迫下番茄嫁接苗的生长、叶片ABA和多胺(PAs)含量的变化。结果表明,嫁
(±)JA和(±)ABA对蚕豆叶片气孔运动的影响,刘新,李云,以蚕豆叶片下表皮为材料研究了(±)JA、亚麻酸和(±)ABA对气孔运动的影响,并初步探讨了(±)JA与(±)ABA在调控气孔运动上的关系。结果表