美文网首页C++多线程
C++11 实现简单的阻塞队列

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

作者: 不动点P | 来源:发表于2020-04-12 15:45 被阅读0次

    一个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);
    }
    

    相关文章

      网友评论

        本文标题:C++11 实现简单的阻塞队列

        本文链接:https://www.haomeiwen.com/subject/vbtvmhtx.html