C++11 - 基于无锁队列的单生产者单消费者模型
时间: 2024-03-01 10:51:19 浏览: 19
基于无锁队列的单生产者单消费者模型可以使用C++11中的atomic和memory_order来实现。以下是一个简单的实现示例:
```
#include <atomic>
#include <memory>
template<typename T>
class LockFreeQueue {
public:
LockFreeQueue() {
Node* node = new Node;
tail_.store(node, std::memory_order_relaxed);
head_.store(node, std::memory_order_relaxed);
}
~LockFreeQueue() {
T value;
while (pop(value));
Node* node = head_.load(std::memory_order_relaxed);
delete node;
}
void push(const T& value) {
Node* node = new Node(value);
Node* prev_tail = tail_.exchange(node, std::memory_order_acq_rel);
prev_tail->next.store(node, std::memory_order_release);
}
bool pop(T& value) {
Node* head = head_.load(std::memory_order_relaxed);
Node* next = head->next.load(std::memory_order_acquire);
if (!next) {
return false;
}
value = next->value;
head_.store(next, std::memory_order_release);
delete head;
return true;
}
private:
struct Node {
Node() : next(nullptr) {}
Node(const T& value) : value(value), next(nullptr) {}
T value;
std::atomic<Node*> next;
};
std::atomic<Node*> head_;
std::atomic<Node*> tail_;
};
```
在构造函数中,我们创建了一个节点,并将头指针和尾指针都指向该节点。在push操作中,我们创建一个新节点,并使用std::atomic::exchange函数原子地将尾指针指向新节点,并返回原来的尾节点。然后将原来的尾节点的next指针指向新节点。在pop操作中,我们先取出头节点的next指针,如果为nullptr,则说明队列为空,返回false。否则,我们将头指针指向next节点,并返回next节点的值。最后,我们删除原来的头节点。
需要注意的是,在push操作中,我们使用std::memory_order_acq_rel来保证对tail指针的读写操作都是原子的,并且保证任何其他线程在读取tail指针之前都已经完成了对前一个节点的更新操作。在pop操作中,我们使用std::memory_order_acquire来保证对next指针的读取是原子的,并且保证任何其他线程在更新next指针之前都已经完成了对头节点的更新操作。