c++11 <4>多生产者多消费者模式

本文介绍了C++11中如何实现多生产者多消费者模式,涉及两个计数器的维护,分别跟踪生产者生产的数量和消费者消费的数量,并确保产品库在并发访问时的互斥。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

4、多生产者多消费者模式:

- 该模型可以说是前面两种模型的综合,程序需要维护两个计数器,分别是生产者已生产产品的数目和消费者已取走产品的数目。另外也需要保护产品库在多个生产者和多个消费者互斥地访问。


#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 producedItemCounter = 0; //生产者计数
    int consumedItemCounter = 0; //生产者计数
    std::mutex mtx;              // 互斥量,保护产品缓冲区
    std::mutex producedItemCounterMtx; //生产者互斥变量  
    std::mutex consumedItemCounterMtx;//消费者互斥变量
    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.producedItemCounterMtx);  // 仓库产品消费计数器保持多线程互斥

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

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

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

// 消费者任务
void ConsumerTask(int th_ID)
{
    bool readyToExit = false;
    while (true)
    {
        this_thread::sleep_for(std::chrono::seconds(1));
        std::unique_lock<std::mutex> lock(gItemRepository.consumedItemCounterMtx);
        if (gItemRepository.consumedItemCounter < kItemsToProduce)
        {
            int item = ConsumeItem(gItemRepository);    // 消费产品
            gItemRepository.consumedItemCounter++;
            {
                std::lock_guard<std::mutex> lock(stdoutMutex);
                cout << "Consumer " <<th_ID<<" consuming "<< item << "^th item..." << endl;
            }
        }
        else
        {
            readyToExit = true;
        }
        lock.unlock();
        if (readyToExit)
        {
            break;
        }
    }
    {
        std::lock_guard<std::mutex> lock(stdoutMutex);
        cout << "Consumer "<<th_ID<<" 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 consumer1(ConsumerTask,1);
    std::thread consumer2(ConsumerTask,2);
    std::thread consumer3(ConsumerTask,3);
    std::thread consumer4(ConsumerTask,4);

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

    consumer1.join();
    consumer2.join();
    consumer3.join();
    consumer4.join();

    system("pause");
    return 0;
}

仓库空了,消费者等待中...thread id = 140117312349952
Produce 4 Product 1 ^th item...
Produce 3 Product 2 ^th item...
Produce 2 Product 3 ^th item...
Produce 1 Product 4 ^th item...
Consumer 2 consuming 1^th item...
Consumer 3 consuming 2^th item...
Consumer 1 consuming 3^th item...
Consumer 4 consuming 4^th item...
Produce 3 Product 5 ^th item...
Produce 2 Product 6 ^th item...
Consumer 4 consuming 5^th item...
Consumer 1 consuming 6^th item...
仓库空了,消费者等待中...thread id = 140117303957248
Produce 4 Product 7 ^th item...
Consumer 3 consuming 7^th item...
Produce 1 Product 8 ^th item...
Consumer 2 consuming 8^th item...
仓库空了,消费者等待中...thread id = 140117295564544
Produce 2 Product 9 ^th item...
Produce 4 Product 10 ^th item...
Produce 3 Product 11 ^th item...
Consumer 4 consuming 9^th item...
Consumer 1 consuming 10^th item...
Consumer 3 consuming 11^th item...
Produce 1 Product 12 ^th item...
Consumer 2 consuming 12^th item...
仓库空了,消费者等待中...thread id = 140117320742656
Produce 2 Product 13 ^th item...
Produce 4 Product 14 ^th item...
Produce 3 Product 15 ^th item...
Consumer 1 consuming 13^th item...
Consumer 3 consuming 14^th item...
Consumer 4 consuming 15^th item...
Produce 1 Product 16 ^th item...
Consumer 2 consuming 16^th item...
Produce 4 Product 17 ^th item...
Produce 2 Product 18 ^th item...
Consumer 3 consuming 17^th item...
Produce 3 Product 19 ^th item...
Consumer 4 consuming 18^th item...
Consumer 1 consuming 19^th item...
Produce 1 Product 20 ^th item...
Consumer 2 consuming 20^th item...
Producer 2 exit.... 
Consumer 3 exit....
Producer 3 exit.... 
Consumer 4 exit....
Producer 4 exit.... 
Consumer 1 exit....
Producer 1 exit.... 
Consumer 2 exit....
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值