C++11 使用 std::atomic(多写入器,单使用者)的无锁队列
C++11 lockless queue using std::atomic (multi writer, single consumer)
我使用 C++11 中的新std::atomic
生成了无锁(无锁)队列的简单实现。我看不出我在这里做错了什么。
#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)
我可以有一些指示在哪里看或指示我可能做错了什么吗?
谢谢!
您正在取消引用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
会显示的原因。
代码中还有另一个错误,在您开始尝试执行并发排队之前,该错误不会显示。 如果compare_exchange_weak_explicit
失败,则意味着另一个线程设法更改了head
指针,因此,在再次尝试 CAS 之前,您需要将head
指针的新值重新加载到new_node->next
中。 以下方法可以解决问题:
while(!std::atomic_compare_exchange_weak_explicit(
&head_,
&new_node->next,
new_node,
std::memory_order_release,
std::memory_order_relaxed)) {
new_node->next = head_.load(std::memory_order_relaxed);
}
相关文章:
- boost::进程间消息队列引发错误
- 如果我只是不访问queue_front节点的子节点,而是将它们推到队列中呢?还是BFS吗
- Android NDK传感器向事件队列报告奇怪的间隔
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 按对象的特定方法按升序排列的C++优先级队列
- 使用2个键的cpp-stl::优先级队列排序不正确
- 我是否需要在下一次转移时将所有权*转移回转移队列
- 在一个读写器队列中,我可以用volatile替换原子吗
- 为什么我的多线程作业队列崩溃
- 尝试将lambda函数放在队列中时出现一般分配器错误(可能是与unique_ptr有关的错误)
- 使用"Task"函数指针队列定义作业管理器
- 在c++队列中使用pop和visit实现线程安全
- 为什么我需要C++中不同的排序格式来对这个USACO代码上的数组和优先级队列进行排序
- 打印优先级队列
- 共享队列的线程安全
- 带自定义比较器的最小优先级队列
- 在 Vulkan Qt 中获取队列系列
- 堆栈和队列是否像C++中的数组一样传递?
- 生产者/使用者,如何确保在关闭所有使用者之前耗尽线程安全队列
- C++11 使用 std::atomic(多写入器,单使用者)的无锁队列