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);
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....