生产者消费者问题是多线程并发中一个非常经典的问题。我在这里实现了一个基于C++11的,单生产者单消费者的版本,供大家参考。
#include <windows.h> #include <iostream> #include <cstdlib> #include <mutex> #include <thread> #include <condition_variable> const int bufferSize=10; struct ItemRepository { int item_buffer[bufferSize]; int write_pos; //current position of producer int read_pos; //current position of consumer std::condition_variable not_empty_con; std::condition_variable not_full_con; std::mutex mtx; }itemRepository; void produce_one_item(ItemRepository*ir) { if (!ir) return; int* item_buffer = ir->item_buffer; std::unique_lock<std::mutex> lock(ir->mtx); if (ir->write_pos == ir->read_pos&& item_buffer[ir->write_pos] == 1)//the repository is full { std::cout << "The producer is waiting for an empty." << std::endl; ir->not_full_con.wait(lock); } item_buffer[ir->write_pos] = 1;//now the buffer in this position is full std::cout << "The producer produces a new item on " << ir->write_pos << std::endl; ir->write_pos++; ir->not_empty_con.notify_all();//notify the consumer to consume items if (ir->write_pos == bufferSize) ir->write_pos = 0; } void consume_one_item(ItemRepository*ir) { if (!ir) return; int* item_buffer = ir->item_buffer; std::unique_lock<std::mutex> lock(ir->mtx); if (ir->read_pos == ir->write_pos&& item_buffer[ir->write_pos] == 0)//the repository is empty { std::cout << "The consumer is waiting for items." << std::endl; ir->not_empty_con.wait(lock); } item_buffer[ir->read_pos] = 0;//now the buffer in this position is empty std::cout << "The consumer consumes an item on " << ir->read_pos << std::endl; ir->read_pos++; ir->not_full_con.notify_all();//notify the producer to produce new items if (ir->read_pos == bufferSize) ir->read_pos = 0; } void produceTask() { for (int i = 0; i < 50; i++) produce_one_item(&itemRepository); } void consumeTask() { for (int i = 0; i < 50; i++) { Sleep(1); consume_one_item(&itemRepository); } } void initializeRepository(ItemRepository*ir) { if (!ir) return; ir->read_pos = 0; ir->write_pos = 0; } int main() { initializeRepository(&itemRepository); std::thread producer(produceTask); std::thread consumer(consumeTask); producer.join(); consumer.join(); system("pause"); return 0; }
注意我判断item_buffer中的物品是否全空或者全满的条件:生产者和消费者的位置相等时,若该位置上为空则buffer全空,若为满则buffer全满。