为什么std :: atomic <t> :: compare_exchange_ *不应该遭受ABA问题?</t>

时间:2013-11-24 11:03:33

标签: c++ multithreading atomic lock-free compare-and-swap

在一些论坛和书籍中(即 C ++ Concurrency in Action ),有一个很好的多生产者/多用户堆栈示例,在 pop 实现中,他们通常会这样做以下内容:


// head is an std::atomic<node*> variable
node *old_head = head.load();
while(old_head && !head.compare_exchange_weak(old_head, old_head->next));
...
为什么使用 std :: atomic&lt; T&gt; :: compare_exchange _ * 会阻止ABA问题?
让我们说:

  • old_head-&gt; next 在线程被抢占之前得到已解决(就在 compare_exchange_weak 之前)
  • 然后BA情景发生
  • 线程恢复后
  • head == old_head 有效;在这种情况下, old_head-&gt; next 将再次已解决,指向无效的内存位置
  • compare_exchange_weak 将被执行,将通过,但值 old_head-&gt; next 仍然是

然后会发生与ABA相关的问题。

我相信我错过了一些东西。我在这里缺少什么?

干杯

1 个答案:

答案 0 :(得分:2)

是的,你会遇到ABA问题。

尽管如此,我认为这无关紧要,因为你所指的实现(在CiA中列出7.3)无论如何都是无效的,它正在泄漏节点。

如果我们看一下最简单的引用计数实现,那么使用无锁std::shared_ptr(在CiA中列出7.9)的实现,我们发现问题不会发生。使用共享指针时,old_head不会被删除,因为我们的线程仍保留对它的引用,因为无法在旧头的内存地址中创建新创建的头。

官方Concurrency in Action Manning forums上还有一个关于堆栈实现中ABA问题的帖子。