CAS的ABA问题

ABA问题本身并没有什么难理解的,可以简单用一句话来概括:线程1准备用CAS将变量的值由A替换为B,在此之前,线程2将变量的值由A替换为C,又由C替换为A,然后线程1执行CAS时发现变量的值仍然为A,所以CAS成功。

当然,如果仅仅关心最终的值是否符合预期,ABA问题并没有什么影响,这也是为什么大多数情况下我们依然可以使用AtomicInteger等数值CAS类不出问题的原因

但是如果CAS操作的内存对象包含数值之外的意义,比如说链表之间的引用,就可能出现bug。比如链表A->B->C,执行操作CAS(A,B), 将链表头换成B,如果操作过程中其他线程将链表变成A->C,执行CAS(A,B)发现连表头A并没有改变,修改成功,导致链表变成B->null,这在某些情况下就会出现问题。

ABA的问题本质上是由于CAS在执行Compare的时候,比较的信息不够充分导致的。前例修改链表,比较链表头的时候仅仅比较了A本身是否变更,忽略了A的关联关系的变化。如果我们在做比较的时候,进一步比较链表头的下级是否变化,自然可以发现A其实发生了变化,Caompare结果应该为false。

更常见的解决ABA问题的方法是增加版本属性,每次修改后版本相应变化,那么在做Compare的时候对版本也做一次校验,自然就可以解决ABA问题。JDK中提供了AtomicStampedReference带版本校验的CAS实现。

发表评论

电子邮件地址不会被公开。

80 − 71 =