无锁队列的基本介绍
一个关于无锁队列的多线程读写代码示例。在这里,我提供一个简单的示例来说明这个问题。
在使用无锁队列时,需要注意以下几点:
使用原子操作来实现对队列的读写操作,以避免多线程同时访问同一数据导致的竞争条件问题。
当队列为空或已满时,需要使用特殊的标记来表示队列的状态。
使用链表来实现的无锁队列
下面是一个使用无锁队列的多线程读写代码示例:
#include <atomic> #include <thread> #include <iostream> template <typename T> class LockFreeQueue { public: LockFreeQueue() : m_head(new Node), m_tail(m_head.load()) {} ~LockFreeQueue() { while (Node* const old_head = m_head) { m_head = old_head->next; delete old_head; } } void enqueue(T value) { Node* const new_node = new Node(value); Node* old_tail = m_tail.exchange(new_node); old_tail->next = new_node; } bool dequeue(T& value) { Node* old_head = m_head; Node* new_head; do { if (old_head->next == nullptr) { return false; } new_head = old_head->next; } while (!m_head.compare_exchange_weak(old_head, new_head)); value = new_head->value; delete old_head; return true; } private: struct Node { T value; Node* next; Node() : next(nullptr) {} Node(T value) : value(value), next(nullptr) {} }; std::atomic<Node*> m_head; std::atomic<Node*> m_tail; }; int main() { LockFreeQueue<int> queue; std::thread t1([&queue]() { for (int i = 0; i < 10; ++i) { queue.enqueue(i); } }); std::thread t2([&queue]() { int value = 0; while (value < 9) { if (queue.dequeue(value)) { std::cout << "Dequeued value: " << value << std::endl; } } }); t1.join(); t2.join(); return 0; }
这段代码实现了一个无锁队列,其中enqueue()函数用于向队列中添加元素,dequeue()函数用于从队列中取出元素。在这个示例中,我们使用了C++11中的std::atomic来实现原子操作,以确保多线程访问时的线程安全。同时,我们使用了compare_exchange_weak()函数来确保多线程环境下的原子操作。
以环形队列实现无锁队列
#include <atomic> template <typename T> class LockFreeQueue { public: LockFreeQueue(size_t capacity = 1024) : m_capacity(capacity) { m_data = new T[m_capacity]; m_head.store(0, std::memory_order_relaxed); m_tail.store(0, std::memory_order_relaxed); } ~LockFreeQueue() { delete[] m_data; m_data = nullptr; } bool push(const T& item) { size_t tail = m_tail.load(std::memory_order_relaxed); size_t head = m_head.load(std::memory_order_acquire); size_t count = tail - head; if (count >= m_capacity - 1) { return false; } m_data[tail % m_capacity] = item; m_tail.store(tail + 1, std::memory_order_release); return true; } bool pop(T& item) { size_t head = m_head.load(std::memory_order_relaxed); size_t tail = m_tail.load(std::memory_order_acquire); size_t count = tail - head; if (count == 0) { return false; } item = m_data[head % m_capacity]; m_head.store(head + 1, std::memory_order_release); return true; } private: T* m_data; size_t m_capacity; std::atomic<size_t> m_head; std::atomic<size_t> m_tail; };
这个队列是一个环形队列,使用了两个原子变量 m_head
和 m_tail
分别表示队列头和队列尾,通过利用原子操作保证线程安全,实现了无锁的操作。同时,使用了 memory_order
来保证数据的可见性和原子性。