Producer-consumer problem (Producer: 1, Consumer: 1, Buffer: 1)

The producer-consumer problem is a well-known thread synchronization problem, which is described as follows:

There is a producer producing products, and these products will be provided to several consumers for consumption. In order to enable the producer and consumer to execute concurrently, a buffer pool with multiple buffers is set between the two, and the producer will The products it produces are put into a buffer, and consumers can take products from the buffer for consumption. Obviously, the producers and consumers must maintain synchronization, that is, consumers are not allowed to take products from an empty buffer. , and does not allow the producer to re-release product into a buffer that has already been placed in the product.


First assume that there is only one producer and consumer, and there is only one buffer.

First. The removal of product from the buffer and the delivery of product to the buffer must be mutually exclusive. This can be done with critical sections and mutexes .

second. The producer has to wait for the buffer to be empty, so that the product can be put in, and the consumer has to wait for the buffer to be not empty, so that the product can be taken out for consumption. And because there are two waiting processes, so use two events or semaphores to control.


The code is implemented as follows:

//1 producer 1 consumer 1 buffer  
//Use two events, one for buffer empty and one for buffer full.  
// use another key segment to control access to the buffer  
#include <stdio.h>  
#include <process.h>  
#include <windows.h>  


#include<iostream>
#include<iomanip>
using namespace std;

//set console output color  
//SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), wAttributes);  
const int iProduceNumber = 10;//Number of production products
int iGlobBuffer;//Global buffer


CRITICAL_SECTION csGlobBuffer;//Key segment to control buffer access
HANDLE hEventBufferEmpty;//Buffer empty
HANDLE hEventBufferFull;//Buffer full


// Producer thread function
UINT WINAPI ProducerProc(PVOID pParam){
	for(int i = 0; i < iProduceNumber; i++){
		//Wait for the buffer to be empty
		WaitForSingleObject(hEventBufferEmpty, INFINITE);

		//mutually exclusive access buffer
		EnterCriticalSection(&csGlobBuffer);
		iGlobBuffer = (i + 1) * 100;
		cout << "producer puts data" << iGlobBuffer << "puts data into buffer" << endl;
		LeaveCriticalSection(&csGlobBuffer);

		//Notify buffer has new data
		SetEvent (hEventBufferFull);
		Sleep(10);//Actively give up the CPU
	}
	return 0;
}
// consumer thread function  
UINT WINAPI ConsumerProc(PVOID pParam){
	volatile bool bContinue = true;
	while(bContinue){
		//Wait for data in the buffer  
		WaitForSingleObject(hEventBufferFull, INFINITE);

		//mutually exclusive access buffer
		EnterCriticalSection(&csGlobBuffer);
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN);
		cout << "The consumer fetches data from the buffer" << iGlobBuffer << endl;
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
		if((iGlobBuffer/100) == iProduceNumber)				bContinue = false;
		LeaveCriticalSection(&csGlobBuffer);

		//Notify buffer is empty
		SetEvent (hEventBufferEmpty);
		Sleep(10);//Actively give up the CPU
	}
	return 0;
}

void main()
{
	InitializeCriticalSection(&csGlobBuffer);
	//Auto reset event, initial buffer is empty
	hEventBufferEmpty = CreateEventW(NULL, FALSE, TRUE, NULL);
	//Auto reset event, initially there is no data in the buffer
	hEventBufferFull = CreateEventW(NULL, FALSE, FALSE, NULL);

	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);

	HANDLE hThreads[2];
	hThreads[0] = (HANDLE)_beginthreadex(NULL, 0, ProducerProc, NULL, 0, NULL);
	hThreads[1] = (HANDLE)_beginthreadex(NULL, 0, ConsumerProc, NULL, 0, NULL);
	WaitForMultipleObjects(2, hThreads, TRUE, INFINITE);
	CloseHandle(hThreads[0]);
	CloseHandle(hThreads[1]);

	cout << "The main thread will exit after waiting for two sub-threads!" << endl;
	/// Destroy key segments and events
	DeleteCriticalSection(&csGlobBuffer);
	CloseHandle(hEventBufferEmpty);
	CloseHandle(hEventBufferFull);
}


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325762758&siteId=291194637