并发编程种的 ABA 问题?

「这是我参与 11 月更文挑战的第 12 天,活动详情查看:2021最后一次更文挑战」。

你好,我是悟空呀。今天给大家带来的大厂面试题是:

ABA 问题?

并发编程种的 ABA 问题

因为 CAS 需要在操作值的时候,检查值有没有发生变化,如果没有发生变化则更新,但是如果一个值原来是A,变成了 B,又变成了 A,那么使用 CAS 进行检查时会发现它的值没有发生变化,但是实际上却变化了。

解决方案

ABA 问题的解决思路就是使用版本号。在变量前面追加上版本号,每次变量更新的时候把版本号加 1,那么 A→B→A 就会变成 1A→2B→3A。

从Java 1.5开始,JDK 的 Atomic 包里提供了一个类 AtomicStampedReference 来解决 ABA 问题。这个类的compareAndSet 方法的作用是首先检查当前引用是否等于预期引用,并且检查当前标志是否等于预期标志,如果全部相等,则以原子方式将该引用和该标志的值设置为给定的更新值。

原子类AtomicStampedReference的底层代码:

比较并替换方法compareAndSet

compareAndSet 源码

expectedReference:期望值

newReference:替换值

expectedStamp:期望版本号

newStamp:替换版本号

先比较期望值 expectedReference 和当前值是否相等,以及期望版本号和当前版本号是否相等,如果两者都相等,则表示没有被修改过,可以进行替换。

举例说明

甲乙线程想改变三角形 A 的形状,乙线程先改成了四边形,后又改成了三角形,三角形 A1->四边形 V2-> 三角形 A3。

当甲线程想改变 A3 为五边形时报错,因为三角形经过已线程修改后,前后版本号不一样,被判定为已修改过,其他线程不能修改。这样就防止了 ABA 问题。

举例说明

猜你喜欢

转载自juejin.im/post/7031565068558942221