c++ 无锁队列的简单实现

本文介绍了无锁队列的概念,提供了使用C++11的std::atomic实现的无锁队列代码示例,包括基于链表和环形结构的两种实现方式,强调了原子操作在确保线程安全中的重要性。

无锁队列的基本介绍

一个关于无锁队列的多线程读写代码示例。在这里,我提供一个简单的示例来说明这个问题。
在使用无锁队列时,需要注意以下几点:
使用原子操作来实现对队列的读写操作,以避免多线程同时访问同一数据导致的竞争条件问题。
当队列为空或已满时,需要使用特殊的标记来表示队列的状态。
使用链表来实现的无锁队列
下面是一个使用无锁队列的多线程读写代码示例:

#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_headm_tail 分别表示队列头和队列尾,通过利用原子操作保证线程安全,实现了无锁的操作。同时,使用了 memory_order 来保证数据的可见性和原子性。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值