c++ 同步阻塞队列

参考:《C++11深入应用》

用同步阻塞队列解决生产者消费者问题。

生产者消费者问题:

有一个生产者在生产产品,这些产品将提供给若干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置一个有多个缓冲区的缓冲池,

生产者将它生产的产品放入一个缓冲区中,消费者可以从缓冲区中取走产品进行消费,所有生产者和消费者都是异步方式运行的,但它们必须保持同步,

即不允许消费者到一个空的缓冲区中取产品,也不允许生产者向一个已经装满产品且尚未被取走的缓冲区中投放产品。

//SyncQueue.hpp
#include <list>
#include <mutex>
#include <condition_variable>
#include <iostream>

template<typename T>
class SyncQueue
{
private:
    bool IsFull() const
    {
        return m_queue.size() == m_maxSize;
    }

    bool IsEmpty() const
    {
        return m_queue.empty();
    }

public:
    SyncQueue(int maxSize) : m_maxSize(maxSize)
    {
    }

    void Put(const T& x)
    {
        std::lock_guard<std::mutex> locker(m_mutex);

        while (IsFull())
        {
            std::cout << "the blocking queue is full,waiting..." << std::endl;
            m_notFull.wait(m_mutex);
        }
        m_queue.push_back(x);
        m_notEmpty.notify_one();
    }

    void Take(T& x)
    {
        std::lock_guard<std::mutex> locker(m_mutex);

        while (IsEmpty())
        {
            std::cout << "the blocking queue is empty,wating..." << std::endl;
            m_notEmpty.wait(m_mutex);
        }

        x = m_queue.front();
        m_queue.pop_front();
        m_notFull.notify_one();
    }

private:
    std::list<T> m_queue;                  //缓冲区
    std::mutex m_mutex;                    //互斥量和条件变量结合起来使用
    std::condition_variable_any m_notEmpty;//不为空的条件变量
    std::condition_variable_any m_notFull; //没有满的条件变量
    int m_maxSize;                         //同步队列最大的size
};

测试:

//test.cpp

#include "SyncQueue.hpp"
#include <thread>
#include <iostream>
#include <chrono>

SyncQueue<int> syncQueue(5);
void Produce()
{
    for (int i = 0; i < 15; ++i)
    {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        syncQueue.Put(888);
        std::cout<<"put(888)"<<std::endl;
    }
}

void Consume()
{
    int x = 0;

    for (int i = 0; i < 5; ++i)
    {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        syncQueue.Take(x);
        std::cout << "take(888)" << std::endl;
    }
}

int main(void)
{
    std::thread producer(Produce);
    std::thread consumer1(Consume);
    std::thread consumer2(Consume);
    std::thread consumer3(Consume);
    producer.join();
    consumer1.join();
    consumer2.join();
    consumer3.join();

    return 0;
}
时间: 2024-10-16 19:15:44

c++ 同步阻塞队列的相关文章

多线程之消费者生产者模式加入阻塞队列

队列相关资料: http://chenjumin.iteye.com/blog/2182322 http://blog.csdn.net/luohuacanyue/article/details/16359777 Queue ------------ 1.ArrayDeque, (数组双端队列) 2.PriorityQueue, (优先级队列) 3.ConcurrentLinkedQueue, (基于链表的并发队列) 4.DelayQueue, (延期阻塞队列)(阻塞队列实现了BlockingQ

阻塞队列和生产者-消费者模式、DelayQueue

1.ArrayDeque, (数组双端队列) 2.PriorityQueue, (优先级队列) 3.ConcurrentLinkedQueue, (基于链表的并发队列) 4.DelayQueue,                                         (延期阻塞队列)(阻塞队列实现了BlockingQueue接口) 5.ArrayBlockingQueue,           (基于数组的并发阻塞队列) 6.LinkedBlockingQueue,        (基

同步容器、并发容器、阻塞队列、双端队列

一.同步容器 主要代表有Vector和Hashtable,以及Collections.synchronizedXxx等. 锁的粒度为当前对象整体. 迭代器是及时失败的,即在迭代的过程中发现被修改,就会抛出ConcurrentModificationException. 二.并发容器 主要代表有ConcurrentHashMap.CopyOnWriteArrayList.ConcurrentSkipListMap.ConcurrentSkipListSet. 锁的粒度是分散的.细粒度的,即读和写是

阻塞队列和生产者-消费者模式

阻塞队列提供了可阻塞的put和take方法.如果队列满了put将阻塞到有空间可用,如果队列为空,take将阻塞到有元素可用.队列可以是有界和无界的,无界的队列put将不会阻塞. 阻塞队列支持生产者消费者模式,该模式将找出需要完成的工作,和执行工作分开.生产者-消费者模式能简化开发过程,因为消除了生产者和消费者之间的代码依赖性,此外,该模式还将生产数据的过程和使用数据的过程解耦开来. 在基于阻塞队列构建的生产者-消费者设计中个,当数据生成时,生产者把数据放入队列,当消费者处理数据时,将从队列中获取

BlockingQueue(阻塞队列)详解

一. 前言 在新增的Concurrent包中,BlockingQueue很好的解决了多线程中,如何高效安全"传输"数据的问题.通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利.本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景. 二. 认识BlockingQueue 阻塞队列,顾名思义,首先它是一个队列,而一个队列在数据结构中所起的作用大致如下图所示: 从上图我们可以很清楚看到,通过一个共享的队列,可以使得数据由

spring线程池ThreadPoolTaskExecutor与阻塞队列BlockingQueue

一: ThreadPoolTaskExecutor是一个spring的线程池技术,查看代码可以看到这样一个字段: private ThreadPoolExecutor threadPoolExecutor; 可以发现,spring的  ThreadPoolTaskExecutor是使用的jdk中的java.util.concurrent.ThreadPoolExecutor进行实现, 直接看代码: @Override protected ExecutorService initializeExe

Michael-Scott非阻塞队列(lock-free)算法的C实现

Michael-Scott非阻塞队列算法,即MS-queue算法,是1 9 9 6 年由Maged . M .Michael and M. L. Scott提出的,是最为经典的并发FIFO队列上的算法,目前很多对并发FIFO队列的研究都是基于这个算法来加以改进的.在共享内存的多核处理器上,这种基于Compare-and-swap(CAS)的算法在性能上要远远优于以前基于锁的算法,并且已经被Java并发包所采用.它的主要特点在于允许多线程并发的.无干扰的访问队列的头和尾. MS-queue算法依赖

Java 并发编程(四)阻塞队列和生产者-消费者模式

阻塞队列 阻塞队列提供了可阻塞的 put 和 take 方法,以及支持定时的 offer 和 poll 方法.如果队列已经满了,那么put方法将阻塞直到有空间可以用:如果队列为空,那么take方法将一直阻塞直到有元素可用.队列可以使有界的,也可以是无界的,无界队列永远都不会充满,因此无界队列上的put方法永远不会阻塞.一种常见的阻塞生产者-消费者模式就是线程池与工作队列的组合,在 Executor 任务执行框架中就体现了这种模式. 意义:该模式能简化开发过程,因为他消除了生产者和消费者类之间的代

Java-SynchronousQueue 阻塞队列小记

在BlockingQueue的子类中有一个SynchronousQueue(同步队列)比较少见,现在做一个简单的介绍,并附加一个简单的例子. SynchronousQueue --JDK1.6介绍: public class SynchronousQueue<E> extends AbstractQueue<E> implements BlockingQueue<E>, Serializable 一种阻塞队列,其中每个插入操作必须等待另一个线程的对应移除操作 ,反之亦然