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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM