一、ABA问题的产生
CAS 算法实现一个重要前提需要取出内存中某时刻的数据并在当下时刻比较并替换,那么在这个时间差类会导致数据的变化。
比如说一个线程 one 从内存位置 V 中取出 A ,这时候另一个线程 two 也从内存中取出 A ,并且线程 two 进行了一些操作将值变成了 B ,然后线程 two 又将 V 位置的数据变成 A ,这时候线程 one 进行 CAS 操作发现内存中仍然是 A ,然后线程 one 操作成功。
尽管线程 one 的 CAS 操作成功,但是不代表这个过程就是没有问题的。
简单来说,ABA问题实质上就是忽略掉了主内存中数值变化的过程,仅仅是关注的到的结果,也就是说,如果程序并不需要考虑顾及到主内存中的值得变化的过程,而仅仅关注结果,ABA问题则没有太大的影响。
二、ABA问题的解决
既然ABA问题是由于某一线程忽略了另一线程对主内存中值的改变的过程(改变过的事实),那么如果要解决这个问题,最容易想到的办法就是为主内存中的值添加版本号。
比如说:
每瓶水生产生出来都会有不同的生产编号(修改和没有修改过的值的版本),但是同一款水的大小以及价格都是一样的(值相同) ,我们可以借助这个办法,对主内存中的值添加版本号。
也就意味着,虽然主内存中的值是相同的,但是由于版本不同,另一线程在做CAS的时候就会发现主内存中的值被更改过的事实。更简单的说,可以把具有不同版本号的值想象成完全不同的两个个体。
public AtomicStampedReference(V initialRef, int initialStamp) {
pair = Pair.of(initialRef, initialStamp);
}
JAVA中的AtomicStampedReference类中添加了Stamp字段,当不同线程每一次对该类所引用的值的操作时,Stamp字段就会自加以区分不同版本的值。