c++11 多生產者單消費者模式

3、多生產者單消費者模式:

- 與單生產者和單消費者模型不同的是,多生產者-單消費者模型中可以允許多個生產者同時向產品庫中放入產品。所以除了保護產品庫在多個讀寫線程下互斥之外,還需要維護生產者放入產品的計數器


#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <deque>
using namespace std;

static const int kItemsToProduce = 20;//定義生產者能夠生產的最大產品個數
std::mutex stdoutMutex;//多線程標準輸出 同步鎖

struct ItemRepository
{
    deque<int> itemQueue;   // 這裏用隊列代表倉庫緩衝區
    int MaxSize = 10;       // 倉庫所容納的產品最大個數
    int itemCounter=0;
    std::mutex mtx;         // 互斥量,保護產品緩衝區
    std::mutex itemCounterMtx;
    std::condition_variable repository_notFull;     // 條件變量, 指產品倉庫緩衝區不爲滿
    std::condition_variable repository_notEmpty;    // 條件變量, 指產品倉庫緩衝區不爲空
}gItemRepository;   // 產品庫全局變量,生產者和消費者操作該變量.

typedef struct ItemRepository ItemRepository;


// 生產 產品
void ProduceItem(ItemRepository &itemRepo, int item)
{
    std::unique_lock<std::mutex> lock(itemRepo.mtx);
    itemRepo.repository_notFull.wait(lock, [&itemRepo] {
        bool full = itemRepo.itemQueue.size() >= itemRepo.MaxSize;
        if (full)
        {
            std::lock_guard<std::mutex> lock(stdoutMutex);
            cout << "倉庫滿了,生產者等待中..." << "thread id = " << std::this_thread::get_id() << endl;
        }
        return !full;
    });

    itemRepo.itemQueue.push_back(item);         // 倉庫放入產品
    itemRepo.repository_notEmpty.notify_all();  // 通知消費者倉庫不爲空
    lock.unlock();  // 釋放鎖
}

// 消費 產品
int ConsumeItem(ItemRepository &itemRepo)
{
    int data;
    std::unique_lock<std::mutex> lock(itemRepo.mtx);

    // 等待信號不爲空的通知,wait 第二參數爲true時 向下執行,否則一直等待
    itemRepo.repository_notEmpty.wait(lock, [&itemRepo] {
        bool empty = itemRepo.itemQueue.empty();
        if (empty)
        {
            std::lock_guard<std::mutex> lock(stdoutMutex);
            cout << "倉庫空了,消費者等待中..." << "thread id = " << std::this_thread::get_id() << endl;
        }

        return !empty;
    });

    data = itemRepo.itemQueue.front();
    itemRepo.itemQueue.pop_front();
    itemRepo.repository_notFull.notify_all();
    lock.unlock();
    return data;
}

// 生產者任務
void ProducerTask(int th_ID)
{
    bool readyToExit = false;
    while (true)
    {
        //
        this_thread::sleep_for(std::chrono::seconds(1));
        std::unique_lock<std::mutex> lock(gItemRepository.itemCounterMtx);  // 倉庫產品消費計數器保持多線程互斥

        if (gItemRepository.itemCounter < kItemsToProduce)
        {
            gItemRepository.itemCounter++;
            ProduceItem(gItemRepository, gItemRepository.itemCounter); // 生產產品
            {
                std::lock_guard<std::mutex> lock(stdoutMutex);
                cout << "Produce Thread " <<th_ID<<"the "<< gItemRepository.itemCounter << " ^th item..." << endl;
            }
        }
        else
        {
            readyToExit = true;
        }

        lock.unlock();
        if (readyToExit)
            break;
    }

    {
        std::lock_guard<std::mutex> lock(stdoutMutex);
        cout << "Producer Thread "<<th_ID<<"exit.... " << endl;
    }
}

// 消費者任務
void ConsumerTask()
{
    static int item_consumed = 0;
    while (true)
    {
        //this_thread::sleep_for(std::chrono::seconds(1));
        item_consumed++;
        if (item_consumed <= kItemsToProduce)
        {
            int item = ConsumeItem(gItemRepository);    // 消費產品
            {
                std::lock_guard<std::mutex> lock(stdoutMutex);
                cout << "Consume the " << item << "^th item..." << endl;
            }
        }
        else
        {
            break;
        }

    }
    {
        std::lock_guard<std::mutex> lock(stdoutMutex);
        cout << "Consumer Thread "<<" exit...." << endl;
    }
}

int main()
{
    std::thread producer1(ProducerTask,1);
    std::thread producer2(ProducerTask,2);
    std::thread producer3(ProducerTask,3);
    std::thread producer4(ProducerTask,4);
    std::thread consumer(ConsumerTask);

    producer1.join();
    producer2.join();
    producer3.join();
    producer4.join();
    consumer.join();

    system("pause");
    return 0;
}

倉庫空了,消費者等待中...thread id = 140157878253312
Produce Thread 3the 1 ^th item...
Produce Thread 2the 2 ^th item...
Produce Thread 4the 3 ^th item...
Consume the 1^th item...
Consume the 2^th item...
Consume the 3^th item...
倉庫空了,消費者等待中...thread id = 140157878253312
Produce Thread 1the 4 ^th item...
Consume the 4^th item...
倉庫空了,消費者等待中...thread id = 140157878253312
Produce Thread 2the 5 ^th item...
Produce Thread 3the 6 ^th item...
Produce Thread 4the 7 ^th item...
Consume the 5^th item...
Consume the 6^th item...
Consume the 7^th item...
倉庫空了,消費者等待中...thread id = 140157878253312
Produce Thread 1the 8 ^th item...
Consume the 8^th item...
倉庫空了,消費者等待中...thread id = 140157878253312
Produce Thread 3the 9 ^th item...
Produce Thread 2the 10 ^th item...
Produce Thread 4the 11 ^th item...
Consume the 9^th item...
Consume the 10^th item...
Consume the 11^th item...
倉庫空了,消費者等待中...thread id = 140157878253312
Produce Thread 1the 12 ^th item...
Consume the 12^th item...
倉庫空了,消費者等待中...thread id = 140157878253312
Produce Thread 2the 13 ^th item...
Produce Thread 3the 14 ^th item...
Produce Thread 4the 15 ^th item...
Consume the 13^th item...
Consume the 14^th item...
Consume the 15^th item...
倉庫空了,消費者等待中...thread id = 140157878253312
Produce Thread 1the 16 ^th item...
Consume the 16^th item...
倉庫空了,消費者等待中...thread id = 140157878253312
Produce Thread 3the 17 ^th item...
Produce Thread 2the 18 ^th item...
Produce Thread 4the 19 ^th item...
Consume the 17^th item...
Consume the 18^th item...
Consume the 19^th item...
倉庫空了,消費者等待中...thread id = 140157878253312
Produce Thread 1the 20 ^th item...
Consume the 20^th item...
Consumer Thread  exit....
Producer Thread 2exit.... 
Producer Thread 3exit.... 
Producer Thread 4exit.... 
Producer Thread 1exit.... 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章