C++ 实现一个简易的阻塞队列

本文介绍了如何使用C++11的条件变量来实现一个阻塞队列,详细阐述了阻塞队列在多线程中的作用以及生产者和消费者模型。文中给出了具体的实现代码,通过一个例子展示了阻塞队列如何在主线程(生产者)与工作线程(消费者)之间进行数据交换。
摘要由CSDN通过智能技术生成

阻塞队列是多线程中常用的数据结构,对于实现多线程之间的数据交换、同步等有很大作用。

阻塞队列常用于生产者和消费者的场景,生产者是向队列里添加元素的线程,消费者是从队列里取元素的线程。简而言之,阻塞队列是生产者用来存放元素、消费者获取元素的容器。

考虑下,这样一个多线程模型,程序有一个主线程 master 和一些 worker 线程,master 线程负责接收到数据,给 worker 线程分配数据,worker 线程取得一个任务后便可以开始工作,如果没有任务便阻塞住,节约 cpu 资源。

  • master 线程 (生产者):负责往阻塞队列中塞入数据,并唤醒正在阻塞的 worker 线程。
  • workder 线程(消费者):负责从阻塞队列中取数据,如果没有数据便阻塞,直到被 master 线程唤醒。

那么怎样的数据结构比较适合做这样的唤醒呢?显而易见,是条件变量,在 c++ 11 中,stl 已经引入了线程支持库。

C++11 中条件变量

条件变量一般与一个 互斥量 同时使用,使用时需要先给互斥量上锁,然后条件变量会检测是否满足条件,如果不满足条件便会暂时释放锁,然后阻塞线程。
c++ 11使用方法主要如下:

#include <mutex>
#include <condition_value>
// 互斥量与条件变量
std::mutex m_mutex;
std::condition_value m_condition;

// 请求信号的一方
std::unique_lock<std::mutex> lock(mutex);
while(xxx)
{
   
    // 这里会先释放 lock,
    // 如果有信号唤醒的话,会重新加锁。
    m_condition.wait(lock);
}

// 发送消息进行同步的一方
{
   
    std::unique_lock<std::mutex> lock(mutex);
    // 唤醒其他正在 wait 的线程
    m_condition.notify_all();
}

用 C++11 实现阻塞队列

我们使用条件变量包装 STL 中的 queue 就可以实现阻塞队列功能,如果有兴趣,甚至可以自己实现一个效率更高的队列数据结构。

我们先假设一下阻塞队列需要如下接口:

  1. push 将一个变量塞入队列;
  2. take 从队列中取出一个元素;
  3. size 查看队列有多少个元素;
template <typename T>
class BlockingQueue
{
   
public:
    BlockingQueue();
    void push(T&& value);
    T take();
    size_t size() const;
    
private:
    // 实际使用的数据结构队列
    std::queue<T> m_data;

    // 条件变量
    std::mutex m_mutex;
    std::condition_variable m_condition;
};

push 一个变量时,我们需要先加锁,加锁成功后才可以压入变量,这是为了线程安全。压入变量后,就可以发送信号通知正在阻塞的条件变量。

    void push(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值