如何解决 ABA 问题?
ABA 问题的主要解决方案是引入版本号。Java提供了一个带有版本号的原子引用类AtomicStampedReference
,它可以解决ABA问题。
AtomicStampedReference
通过一对数据和版本号联合控制操作,每次改变都会导致版本号增加,这样即使A->B->A,版本号也会发生改变,从而避免了ABA问题。
举个例子,我们可以将初始值为1的版本号和初始值为A的引用值一起传给AtomicStampedReference
,每次改变引用值的时候都会让版本号加1,这样如果有其他线程想要通过CAS操作改变引用值,需要输入预期的引用值和预期的版本号,只有两者都符合当前的引用值和版本号,才会改变成功。
AtomicStampedReference<String> atomicStampedReference = new AtomicStampedReference<>("A", 1);
在这个例子中,”A”是初始的引用值,1是初始的版本号。如果有两个线程同时尝试将引用值从”A”改为”B”,那么只有版本号也为1的线程才会改变成功,成功后,版本号会自动加1。这样,即使另一个线程的预期引用值是”A”,但是因为它的预期版本号还是1,所以它的CAS操作会失败。