假设现在你使用链表维护了一个栈,栈中的元素如下:
然后你有一个通过CAS算法实现的pop操作
1.获取当前的栈顶:oldTop = head;
2.获取栈顶元素的下一个元素:nextTop = oldTop.next;
3.使用CAS算法,当栈顶元素为oldTop时,进行更新操作。
4.返回原来的栈顶元素
拿上面ABC三个元素组成的栈来说,head指针首先指向A元素,我们调用pop方法。
oldTop = A;nextTop =B;CAS(&head,期望值[A],原有值[A],更新值[B])。最后我们返回A。
现在我们来看一个场景栈中元素依旧是ABA,有两个线程,线程1执行到了第二步,此时oldTop = A,nextTop = B。然后进行了线程切换,线程2执行了将A出栈、B出栈、A入栈三个操作。此时栈中数据是A->C。
然后切换回线程1进行执行,此时正常的逻辑,线程1应该弹出A,然后C成为新的栈顶。但是线程1的CAS算法进行比较,发现栈顶元素还是A,所以使用nextTop = B去更新了栈顶元素,导致最终栈中的数据变成了B。这就是著名的ABA问题。