C++ condition_variable 實現生產者消費者模型

q1076452761發表於2020-11-12

C++ condition_variable 實現生產者消費者模型

#include <iostream>
#include <thread>
#include <condition_variable>
#include <mutex>
#include <queue>
#include<windows.h>
#include<chrono>
using namespace std;
using namespace std::chrono;
#define PRODUCE_TIME 1000 // 生產 時間 ms
#define CONSUME_TIME 1000 // 消費 時間 ms
#define MAX_SIZE 5 // 緩衝區 儲存容量
#define STOP_FLAG 10 // 結束標誌 消費10個產品 程式結束
int stopflag = 0;

// 緩衝區
mutex bufferMutex;
queue<int> buffer;
int productID = 0;
// 輸出 鎖
mutex printMutex;

mutex NoEmpty;
mutex NoFull;
// 條件變數
condition_variable bufferNoEmpty; 
condition_variable bufferNoFull;

void GetTime()
{
	system_clock::duration d = system_clock::now().time_since_epoch();
	milliseconds mil = duration_cast<milliseconds>(d);
	cout << mil.count() << "毫秒 == ";

}

void Producer()
{
	while (1)
	{

		Sleep(PRODUCE_TIME); // 花時間生產

		unique_lock<mutex> lk(NoFull);
		while (buffer.size() == MAX_SIZE) // 滿
		{
			printMutex.lock();
			GetTime();
			cout << " 緩衝區滿了..." << endl;
			printMutex.unlock();
			// 空閒數 0 需等待
			if (stopflag >= STOP_FLAG)
			{
				printMutex.lock();
				GetTime();
				cout << "已取出限定個數" << endl;
				printMutex.unlock();
				break;
			}
			bufferNoFull.wait(lk);
		}
		if (stopflag >= STOP_FLAG)
		{
			break;
		}
		printMutex.lock();
		GetTime();
		cout << "放入 : " << productID << endl;
		buffer.push(productID++);
		printMutex.unlock();


		if (buffer.size() >= 1)
		{
			bufferNoEmpty.notify_all();
		}

		if (stopflag >= STOP_FLAG)
		{
			break;
		}

	}
	printMutex.lock();
	GetTime();
	cout << "結束生產 " << endl;
	printMutex.unlock();
}

void Consumer()
{
	while (1)
	{
		unique_lock<mutex> lk(NoEmpty);
		while (buffer.empty())
		{
			printMutex.lock();
			GetTime();
			cout << "緩衝區空了..." << endl;
			printMutex.unlock();
			bufferNoEmpty.wait(lk); // 當前 無產品 需要等待生產
		}

		int product = -1;
		printMutex.lock();
		product = buffer.front();
		buffer.pop();
		GetTime();
		cout << "取出 : " << product << endl;
		printMutex.unlock();



		if (buffer.size() < MAX_SIZE)
		{
			bufferNoFull.notify_all(); // 通知 有空閒位置
		}
		Sleep(CONSUME_TIME); // 消費產品
		stopflag++;
		if (stopflag >= STOP_FLAG)
		{

			break;
		}
	}

	printMutex.lock();
	GetTime();
	cout << "結束消費 " << endl;
	printMutex.unlock();
	bufferNoFull.notify_all(); // 通知 生產者 不需要再等待
}
int main()
{
	thread Produce(Producer);
	thread Consume(Consumer);
	//getchar();
	Produce.join();
	Consume.join();
	//getchar();
	lock_guard<mutex> lock(bufferMutex);
	cout << "buffer 剩下個數:" << buffer.size() << endl;
	cout << "下一個生產id: " << productID << endl;

	return 0;
}

相關文章