单个生产者和单个消费者
#include <iostream>
#include <mutex>
#include <condition_variable>
#include <Windows.h>
using namespace std;
const int ITEMREPOSITORY_MAXSIZE = 10;
const int ITEMTOPRODUCE_COUNT = 100;
//使用环形队列
struct ItemRepository
{
int itemBuffer[ITEMREPOSITORY_MAXSIZE];
size_t readPosition;
size_t writePosition;
std::mutex mtx; //仓库锁
std::condition_variable repoNotFull; //仓库满时条件变量
std::condition_variable repoNotEmpty; //仓库空时条件变量
};
void InitRepository(ItemRepository *ir)
{
ir->readPosition = 0;
ir->writePosition = 0;
}
void ProduceItem(ItemRepository *ir, int item)
{
std::unique_lock<std::mutex > lock(ir->mtx);
//当仓库满时,阻塞自己,等待消费者消费
while ((ir->writePosition + 1) % ITEMREPOSITORY_MAXSIZE == ir->readPosition)
{
cout << "Productor is waiting an empty slot..." << endl;
ir->repoNotFull.wait(lock);
}
//有空位,往仓库放入产品
ir->itemBuffer[ir->writePosition] = item;
++ir->writePosition;
//如果写入位置超出环形队列大小上限,移动到开始位置
if (ir->writePosition >= ITEMREPOSITORY_MAXSIZE)
{
ir->writePosition = 0;
}
//通知消费者仓库不为空,快来消费
ir->repoNotEmpty.notify_all();
lock.unlock();
}
int ConsumeItem(ItemRepository *ir)
{
std::unique_lock<mutex> lock(ir->mtx);
//如果仓库为空,阻塞自己,等待生产者放入产品
while (ir->readPosition == ir->writePosition)
{
cout << "repo is empty, consume is waiting a item..." << endl;
ir->repoNotEmpty.wait(lock);
}
//仓库不为空,开始消费产品
int item = ir->itemBuffer[ir->readPosition];
++ir->readPosition;
if (ir->readPosition >= ITEMREPOSITORY_MAXSIZE)
{
ir->readPosition = 0;
}
//通知生产者,我消耗了产品,你赶快再生产
ir->repoNotFull.notify_all();
lock.unlock();
return item;
}
void ProduceTask(ItemRepository *ir)
{
cout << "start to produce item!" << endl;
for (int i = 0; i <= ITEMTOPRODUCE_COUNT; ++i)
{
//Sleep(100); //可以观察仓库为空时输出情况
ProduceItem(ir, i);
}
cout << "produce end!" << endl;
}
void ConsumeTask(ItemRepository *ir)
{
cout << "start to consume!" << endl;
while (true)
{
int item = ConsumeItem(ir);
cout << "I'm is consuming " << item << "th item!" << endl;
if (item == ITEMTOPRODUCE_COUNT)
{
break;
}
}
cout << "consume all productor, cool!" << endl;
}
int main()
{
ItemRepository gItemRepository;
InitRepository(&gItemRepository);
std::thread producer(ProduceTask, &gItemRepository);
std::thread consumer(ConsumeTask, &gItemRepository);
producer.join();
consumer.join();
getchar();
return EXIT_SUCCESS;
}
多个生产者和单个消费者
#include <iostream>
#include <mutex>
#include <condition_variable>
#include <Windows.h>
using namespace std;
const int ITEMREPOSITORY_MAXSIZE = 10;
const int ITEMTOPRODUCE_COUNT = 100;
//使用环形队列
//生产者计数器和锁也可以放仓库外
struct ItemRepository
{
int itemBuffer[ITEMREPOSITORY_MAXSIZE];
size_t readPosition;
size_t writePosition;
int produceCounter;//生产者计数器
std::mutex mtx; //仓库锁
std::mutex produceCounterMutex;//生产者计数锁
std::condition_variable repoNotFull; //仓库满时条件变量
std::condition_variable repoNotEmpty; //仓库空时条件变量
};
void InitRepository(ItemRepository *ir)
{
ir->readPosition = 0;
ir->writePosition = 0;
ir->produceCounter = 0;
}
void ProduceItem(ItemRepository *ir, int item)
{
std::unique_lock<std::mutex > lock(ir->mtx);
//当仓库满时,阻塞自己,等待消费者消费
while ((ir->writePosition + 1) % ITEMREPOSITORY_MAXSIZE == ir->readPosition)
{
cout << "Productor is waiting an empty slot..." << endl;
ir->repoNotFull.wait(lock);
}
//有空位,往仓库放入产品
ir->itemBuffer[ir->writePosition] = item;
++ir->writePosition;
//如果写入位置超出环形队列大小上限,移动到开始位置
if (ir->writePosition >= ITEMREPOSITORY_MAXSIZE)
{
ir->writePosition = 0;
}
//通知消费者仓库不为空,快来消费
ir->repoNotEmpty.notify_all();
lock.unlock();
}
int ConsumeItem(ItemRepository *ir)
{
std::unique_lock<mutex> lock(ir->mtx);
//如果仓库为空,阻塞自己,等待生产者放入产品
while (ir->readPosition == ir->writePosition)
{
cout << "repo is empty, consume is waiting a item..." << endl;
ir->repoNotEmpty.wait(lock);
}
//仓库不为空,开始消费产品
int item = ir->itemBuffer[ir->readPosition];
++ir->readPosition;
if (ir->readPosition >= ITEMREPOSITORY_MAXSIZE)
{
ir->readPosition = 0;
}
//通知生产者,我消耗了产品,你赶快再生产
ir->repoNotFull.notify_all();
lock.unlock();
return item;
}
void ProduceTask(ItemRepository *ir)
{
bool isExit = false;
cout << "thread [" << this_thread::get_id() << "] start to produce item!" << endl;
while (true)
{
//每个线程阻塞自己一秒,否则其他线程有可能抢占不到锁而变成单生产者
this_thread::sleep_for(chrono::seconds(1));
std::unique_lock<std::mutex> lock(ir->produceCounterMutex);
if (ir->produceCounter < ITEMTOPRODUCE_COUNT)
{
++ir->produceCounter;
ProduceItem(ir, ir->produceCounter);
cout << "thread [" << this_thread::get_id() << "] has produced "<< ir->produceCounter << "th item!" << endl;
}
else
{
isExit = true;
}
if (isExit)
{
lock.unlock();
break;
}
lock.unlock();
}
cout << "thread [" << this_thread::get_id() << "] produce end!" << endl;
}
void ConsumeTask(ItemRepository *ir)
{
cout << "start to consume!" << endl;
while (true)
{
int item = ConsumeItem(ir);
cout << "I'm is consuming " << item << "th item!" << endl;
if (item == ITEMTOPRODUCE_COUNT)
{
break;
}
}
cout << "consume all productor, cool!" << endl;
}
int main()
{
ItemRepository gItemRepository;
InitRepository(&gItemRepository);
std::thread producerOne(ProduceTask, &gItemRepository);
std::thread producerTwo(ProduceTask, &gItemRepository);
std::thread consumer(ConsumeTask, &gItemRepository);
producerOne.join();
producerTwo.join();
consumer.join();
getchar();
return EXIT_SUCCESS;
}
单个生产者和多个消费者
#include <iostream>
#include <mutex>
#include <condition_variable>
#include <Windows.h>
#include <chrono>
using namespace std;
const int ITEMREPOSITORY_MAXSIZE = 10;
const int ITEMTOPRODUCE_COUNT = 100;
//使用环形队列
struct ItemRepository
{
int itemBuffer[ITEMREPOSITORY_MAXSIZE];
size_t readPosition;
size_t writePosition;
int consumeCounter;
std::mutex mtx; //仓库锁
std::mutex consumeCounterMutex;
std::condition_variable repoNotFull; //仓库满时条件变量
std::condition_variable repoNotEmpty; //仓库空时条件变量
};
void InitRepository(ItemRepository *ir)
{
ir->readPosition = 0;
ir->writePosition = 0;
ir->consumeCounter = 0;
}
void ProduceItem(ItemRepository *ir, int item)
{
std::unique_lock<std::mutex > lock(ir->mtx);
//当仓库满时,阻塞自己,等待消费者消费
while ((ir->writePosition + 1) % ITEMREPOSITORY_MAXSIZE == ir->readPosition)
{
cout << "Productor is waiting an empty slot..." << endl;
ir->repoNotFull.wait(lock);
}
//有空位,往仓库放入产品
ir->itemBuffer[ir->writePosition] = item;
++ir->writePosition;
//如果写入位置超出环形队列大小上限,移动到开始位置
if (ir->writePosition >= ITEMREPOSITORY_MAXSIZE)
{
ir->writePosition = 0;
}
//通知消费者仓库不为空,快来消费
ir->repoNotEmpty.notify_all();
lock.unlock();
}
int ConsumeItem(ItemRepository *ir)
{
std::unique_lock<mutex> lock(ir->mtx);
//如果仓库为空,阻塞自己,等待生产者放入产品
while (ir->readPosition == ir->writePosition)
{
cout << "repo is empty, consume is waiting a item..." << endl;
ir->repoNotEmpty.wait(lock);
}
//仓库不为空,开始消费产品
int item = ir->itemBuffer[ir->readPosition];
++ir->readPosition;
if (ir->readPosition >= ITEMREPOSITORY_MAXSIZE)
{
ir->readPosition = 0;
}
//通知生产者,我消耗了产品,你赶快再生产
ir->repoNotFull.notify_all();
lock.unlock();
return item;
}
void ProduceTask(ItemRepository *ir)
{
cout << "start to produce item!" << endl;
for (int i = 0; i <= ITEMTOPRODUCE_COUNT; ++i)
{
ProduceItem(ir, i);
}
cout << "produce end!" << endl;
}
void ConsumeTask(ItemRepository *ir)
{
bool isExit = false;
cout << "thread [" << this_thread::get_id() << "start to consume!" << endl;
while (true)
{
//每个线程阻塞自己一秒,否则其他线程有可能抢占不到锁而变成一个线程单消费
this_thread::sleep_for(chrono::seconds(1));
std::unique_lock<std::mutex> lock(ir->consumeCounterMutex);
if (ir->consumeCounter <= ITEMTOPRODUCE_COUNT)
{
int item = ConsumeItem(ir);
cout <<"thread [" << this_thread::get_id() << "] is consuming " << item << "th item!" << endl;
++ir->consumeCounter;
}
else
{
isExit = true;
}
if (isExit)
{
lock.unlock();
break;
}
lock.unlock();
}
cout << "thread [" << this_thread::get_id() << "] consume end, cool!" << endl;
}
int main()
{
ItemRepository gItemRepository;
InitRepository(&gItemRepository);
std::thread producer(ProduceTask, &gItemRepository);
std::thread consumerOne(ConsumeTask, &gItemRepository);
std::thread consumerTwo(ConsumeTask, &gItemRepository);
std::thread consumerThree(ConsumeTask, &gItemRepository);
std::thread consumerFour(ConsumeTask, &gItemRepository);
producer.join();
consumerOne.join();
consumerTwo.join();
consumerThree.join();
consumerFour.join();
getchar();
return EXIT_SUCCESS;
}
多个生产者和多个消费者
#include <iostream>
#include <mutex>
#include <condition_variable>
#include <Windows.h>
using namespace std;
const int ITEMREPOSITORY_MAXSIZE = 10;
const int ITEMTOPRODUCE_COUNT = 100;
//使用环形队列
//生产者计数器和锁也可以放仓库外
struct ItemRepository
{
int itemBuffer[ITEMREPOSITORY_MAXSIZE];
size_t readPosition;
size_t writePosition;
int produceCounter;//生产者计数器
int consumeCounter;//消费者计数器
std::mutex mtx; //仓库锁
std::mutex produceCounterMutex;//生产者计数锁
std::mutex consumeCounterMutex;//消费者计数锁
std::condition_variable repoNotFull; //仓库满时条件变量
std::condition_variable repoNotEmpty; //仓库空时条件变量
};
void InitRepository(ItemRepository *ir)
{
ir->readPosition = 0;
ir->writePosition = 0;
ir->produceCounter = 0;
ir->consumeCounter = 0;
}
void ProduceItem(ItemRepository *ir, int item)
{
std::unique_lock<std::mutex > lock(ir->mtx);
//当仓库满时,阻塞自己,等待消费者消费
while ((ir->writePosition + 1) % ITEMREPOSITORY_MAXSIZE == ir->readPosition)
{
cout << "Productor is waiting an empty slot..." << endl;
ir->repoNotFull.wait(lock);
}
//有空位,往仓库放入产品
ir->itemBuffer[ir->writePosition] = item;
++ir->writePosition;
//如果写入位置超出环形队列大小上限,移动到开始位置
if (ir->writePosition >= ITEMREPOSITORY_MAXSIZE)
{
ir->writePosition = 0;
}
//通知消费者仓库不为空,快来消费
ir->repoNotEmpty.notify_all();
lock.unlock();
}
int ConsumeItem(ItemRepository *ir)
{
std::unique_lock<mutex> lock(ir->mtx);
//如果仓库为空,阻塞自己,等待生产者放入产品
while (ir->readPosition == ir->writePosition)
{
cout << "repo is empty, consume is waiting a item..." << endl;
ir->repoNotEmpty.wait(lock);
}
//仓库不为空,开始消费产品
int item = ir->itemBuffer[ir->readPosition];
++ir->readPosition;
if (ir->readPosition >= ITEMREPOSITORY_MAXSIZE)
{
ir->readPosition = 0;
}
//通知生产者,我消耗了产品,你赶快再生产
ir->repoNotFull.notify_all();
lock.unlock();
return item;
}
void ProduceTask(ItemRepository *ir)
{
bool isExit = false;
cout << "thread [" << this_thread::get_id() << "] start to produce item!" << endl;
while (true)
{
//每个线程阻塞自己一秒,否则其他线程有可能抢占不到锁而变成单生产者
this_thread::sleep_for(chrono::seconds(1));
std::unique_lock<std::mutex> lock(ir->produceCounterMutex);
if (ir->produceCounter < ITEMTOPRODUCE_COUNT)
{
++ir->produceCounter;
ProduceItem(ir, ir->produceCounter);
cout << "thread [" << this_thread::get_id() << "] has produced " << ir->produceCounter << "th item!" << endl;
}
else
{
isExit = true;
}
if (isExit)
{
lock.unlock();
break;
}
lock.unlock();
}
cout << "thread [" << this_thread::get_id() << "] produce end!" << endl;
}
void ConsumeTask(ItemRepository *ir)
{
bool isExit = false;
cout << "thread [" << this_thread::get_id() << "] start to consume!" << endl;
while (true)
{
//每个线程阻塞自己一秒,否则其他线程有可能抢占不到锁而变成一个线程单消费
this_thread::sleep_for(chrono::seconds(1));
std::unique_lock<std::mutex> lock(ir->consumeCounterMutex);
if (ir->consumeCounter < ITEMTOPRODUCE_COUNT)
{
int item = ConsumeItem(ir);
cout <<"thread [" << this_thread::get_id() << "] is consuming " << item << "th item!" << endl;
++ir->consumeCounter;
}
else
{
isExit = true;
}
if (isExit)
{
lock.unlock();
break;
}
lock.unlock();
}
cout << "thread [" << this_thread::get_id() << "] consume end, cool!" << endl;
}
int main()
{
ItemRepository gItemRepository;
InitRepository(&gItemRepository);
std::thread producerOne(ProduceTask, &gItemRepository);
std::thread producerTwo(ProduceTask, &gItemRepository);
std::thread consumerOne(ConsumeTask, &gItemRepository);
std::thread consumerTwo(ConsumeTask, &gItemRepository);
std::thread consumerThree(ConsumeTask, &gItemRepository);
producerOne.join();
producerTwo.join();
consumerOne.join();
consumerTwo.join();
consumerThree.join();
getchar();
return EXIT_SUCCESS;
}