最近我正在阅读Anthony Williams - C ++ Concurrency,我进入了作者建议非阻塞线程安全堆栈实现的章节。在pop()的第一个实现中,据说该方法不是线程安全的。问题是为什么它不是线程安全的?换句话说 - 有人能指出数据竞争的位置吗?
#include <memory>
#include <thread>
#include <iostream>
#include <atomic>
using namespace std;
template <class T>
class lock_free_stack
{
private:
struct Node
{
std::shared_ptr<T> data_;
Node *next;
Node(const T& data): data_(std::make_shared<T>(data))
{
}
};
std::atomic<Node *> head;
public:
lock_free_stack() { head.store(nullptr); }
void push(T const& data)
{
Node* const newNode = new Node(data);
newNode->next = head.load();
while(!head.compare_exchange_weak(newNode->next, newNode));
}
// The following function is not thread-safe
std::shared_ptr<T> pop()
{
Node* old_head = head.load();
while (old_head && !head.compare_exchange_weak(old_head, old_head->next)); // Atomically
unique_ptr<Node> deleter;
if(old_head)
deleter.reset(old_head);
return old_head ? old_head->data_ : std::shared_ptr<T>();
}
};
答案 0 :(得分:3)
竞争条件是一个线程可以评估old_head->next
,只是在调用unique_ptr
的析构函数时(或之后)删除节点old_head
指向。