我使用C ++ 11中的新std::atomic
生成了一个简单的无锁(lockfree)队列实现。我在这里看不出我做错了什么。
#include <atomic>
template<typename T>
class lockless_queue
{
public:
template<typename DataType>
struct node
{
node(const DataType& data)
: data(data), next(nullptr) {}
DataType data;
node* next;
};
lockless_queue()
: head_(nullptr) {}
void produce(const T &data)
{
node<T>* new_node = new node<T>(data);
// put the current value of head into new_node->next
new_node->next = head_.load(std::memory_order_relaxed);
// now make new_node the new head, but if the head
// is no longer what's stored in new_node->next
// (some other thread must have inserted a node just now)
// then put that new head into new_node->next and try again
while(!std::atomic_compare_exchange_weak_explicit(
&head_,
&new_node->next,
new_node,
std::memory_order_release,
std::memory_order_relaxed)) {}
}
node<T>* consume_all()
{
// Reset queue and return head atomically
return head_.exchange(nullptr, std::memory_order_consume);
}
private:
std::atomic<node<T>*> head_;
};
// main.cpp
#include <iostream>
int main()
{
lockless_queue<int> s;
s.produce(1);
s.produce(2);
s.produce(3);
auto head = s.consume_all();
while (head)
{
auto tmp = head->next;
std::cout << tmp->data << std::endl;
delete head;
head = tmp;
}
}
我的输出:
2
1
Segmentation fault (core dumped)
我可以指点一下或者说明我可能做错了吗?
谢谢!
答案 0 :(得分:3)
您要取消引用tmp
而不是head
:
while (head)
{
auto tmp = head->next;
std::cout << tmp->data << std::endl;
delete head;
head = tmp;
}
应该是:
while (head)
{
std::cout << head->data << std::endl;
auto tmp = head->next;
delete head;
head = tmp;
}
这就是3
未出现在您的输出中而Segmentation fault
出现的原因。
答案 1 :(得分:2)
您的代码中有另一个错误,在您开始尝试执行并发排队之前不会显示该错误。如果您的compare_exchange_weak_explicit
失败,则意味着另一个线程设法更改了head
指针,因此在您再次尝试CAS之前,需要重新加载{{1}的新值指针进入head
。以下将解决这个问题:
new_node->next