C++11 实现简单的阻塞队列

一个blocking queue是一个支持 take 和 put 的 queue。

take操作从队列中取出一个元素,如果队列为空,那么take会阻塞到直到队列中有可用元素。

put操作往队列里放入一个元素,如果队列是满,那么put会阻塞到队列有可用空间。

一个简单的blocking queue的实现,首先我们要有一个非常底层的容器,至于是vector还是deque甚至是list都无所谓,我们这里选择deque作为容器。

前面定义的blocking queue是有界的,也就是说元素有上限,所以才会出现满元素阻塞的情况。

我们先从简单的无界阻塞队列开始,默认这个队列可以一直存储元素。于是我们就不用去判断队列满元素的情况了。这个时候我们只需要一个条件变量来判断队列为空并且阻塞就行。大概框架如下。

template<typename T>
class BlockQueue{
    std::deque<T> que;
    std::condition_variable empty;
    std::mutex mtx; // declared for unique_lock;
public:
    T take();
    void put(T elem);
    int size();
}

那么核心的take和put要怎么实现呢?

首先修改队列的操作要加锁,并发编程的时候只要涉及到修改可变变量都必须要加锁,不巧put和take都是在修改队列。

这里使用unique_lock来加锁

std::unique_lock<std::mutex> lock{mtx};

两个操作中只有take操作会出现队列为空的情况,所以take必须判断队列为空,这里使用条件变量

empty.wait(lock, [this]{return !que.empty();});

于是我们的put和take操作就出来了

template<typename T>
T BlockQueue::take(){
     std::unique_lock<std::mutex> lock{mtx};
     empty.wait(lock, [this]{return !que.empty();});
     auto res = que.front():
     que.pop_front():
     return res;
}

template<typename T>
void BlockQueue::put(T elem){
     std::unique_lock<std::mutex> lock{mtx};
     que.push_back(T elem);
}



作者:不动点P
链接:https://www.jianshu.com/p/9dd1b7863667
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

猜你喜欢

转载自blog.csdn.net/qingzhuyuxian/article/details/108463637