首页 > 解决方案 > 这段代码如何不能解决 ABA 问题?

问题描述

我试图了解无锁堆栈中的 ABA 问题。根据维基百科

我们有一个堆栈 A,B,C。

我有以下实现:

class Stack
{
    struct Node { Node* next; };
    std::atomic<Node*> head;
public:

    void push()
    {
        auto node = new Node{ head.load() };
        while(!head.compare_exchange_weak(node->next, node));
    }

    void pop()
    {
        auto old_head = head.load();
        while(!head.compare_exchange_weak(old_head, old_head->next));
    }
};

我知道这个实现并没有解决 ABA 问题,但我不知道为什么。我查看了汇编代码

mov     rax, QWORD PTR [rdx]
$LL2@push:
   lock cmpxchg QWORD PTR [rbx], rdx
   je      SHORT $LN18@push [to exit the function]
   mov     QWORD PTR [rdx], rax <----- **AFTER** the CAS the head->next pointer is loaded
   jmp     SHORT $LL2@push

流行音乐

mov     rax, QWORD PTR [rcx]
$LL2@pop:
   mov     rdx, QWORD PTR [rax]  <----- **BEFORE** the CAS the head->next pointer is loaded
   lock cmpxchg QWORD PTR [rcx], rdx
   jne     SHORT $LL2@pop

汇编代码似乎在执行 CAS 之前加载了 old_head->next 指针。因此,当 thread_1 恢复时,它只会加载指向 C 的正确 next 指针,而这段代码似乎可以解决 ABA 问题。问题一定出在其他地方,我找不到。

标签: c++concurrencyatomic

解决方案


推荐阅读