学习多线程的生产者和消费者系列的相关实践

这篇博客记录了作者学习多线程中生产者-消费者模式的实践过程,通过详细讲解和代码示例,帮助读者理解这一核心概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

昨天很幸运的找到了这个系列的博客 http://blog.youkuaiyun.com/morewindows/article/details/7421759,点击打开链接

学习了一下关于多线程的知识,前面的系列讲解的非常详细,并且对生产消费这一篇(csdn博客无法打开,在其他网址浏览的)做了相关的代码实践记录如下备忘:

/情景1://
//1生产者 1消费者 1缓冲区  
//使用二个事件,一个表示缓冲区空,一个表示缓冲区满。  
//再使用一个关键段来控制缓冲区的访问

//#include <stdio.h>  
//#include <process.h>  
//#include <windows.h>
//
//CRITICAL_SECTION  g_csThreadCode;
//HANDLE  g_hEventFull;//表示缓冲区满
//HANDLE  g_hEventEmpty;//表示缓冲区空
//
//volatile long Datanum; //每次产生或者读取的数据
//const int END_PRODUCE_NUMBER = 10;   //生产产品个数
//unsigned int __stdcall ProduceThread(void *pPM) {
//	for (int i = 0; i < END_PRODUCE_NUMBER; i++) {
//		WaitForSingleObject(g_hEventEmpty, INFINITE); //等待"缓冲区空"事件被触发
//		InitializeCriticalSection(&g_csThreadCode);
//		Datanum = i;
//		printf("产生数据:%d\n",Datanum);
//		LeaveCriticalSection(&g_csThreadCode);
//		SetEvent(g_hEventFull); //触发"缓冲区满"事件
//	}
//	return 0;
//}
//unsigned int __stdcall ConsumeThread(void *pPM) {
//	int ReadData;
//	for (int i = 0; i < END_PRODUCE_NUMBER; i++) {
//		WaitForSingleObject(g_hEventFull, INFINITE); //等待"缓冲区满"事件被触发
//		InitializeCriticalSection(&g_csThreadCode);
//		ReadData = Datanum;
//		printf("消费数据:%d\n", ReadData);
//		LeaveCriticalSection(&g_csThreadCode);
//		SetEvent(g_hEventEmpty); //触发"缓冲区满"事件
//		
//	}
//	return 0;
//}
//int main() {
//
//	//初始化
//	g_hEventFull = CreateEvent(NULL, FALSE, FALSE, NULL);//初始化时将 “g_hEventFull “事件设置为FALSE未激发态
//	g_hEventEmpty = CreateEvent(NULL, FALSE, TRUE, NULL);// 初始化时将 “g_hEventEmpty“事件设置为TRUE激发态
//
//	InitializeCriticalSection(&g_csThreadCode);
//	const int THREADNUM = 2;
//	HANDLE hThread[THREADNUM];
//	hThread[0] =(HANDLE)_beginthreadex(NULL, 0, ProduceThread, NULL, 0, NULL);
//	hThread[1] = (HANDLE)_beginthreadex(NULL, 0, ConsumeThread, NULL, 0, NULL);
//	WaitForMultipleObjects(THREADNUM, hThread, TRUE, INFINITE);
//	CloseHandle(hThread[0]);
//	CloseHandle(hThread[1]);
//
//	//销毁事件和关键段  
//	CloseHandle(g_hEventFull);
//	CloseHandle(g_hEventEmpty);
//	DeleteCriticalSection(&g_csThreadCode);
//	system("pause");
//	return 0;
//}


/情景2://
1生产者 2消费者 4缓冲区  
//用一个信号量A来记录为空的缓冲区个数,另一个信号量B记录非空的缓冲区个数,
//然后生产者等待信号量A,消费者等待信号量B就可以了
//再使用一个关键段来控制缓冲区的访问

//#include <stdio.h>  
//#include <process.h>  
//#include <windows.h>
//const int END_PRODUCE_NUMBER = 8;  //生产产品个数  
//const int BUFFER_SIZE = 4;          //缓冲区个数  
//int g_Buffer[BUFFER_SIZE];          //缓冲池  
//int g_i, g_j;
信号量与关键段  
//CRITICAL_SECTION g_cs;
//HANDLE g_hSemaphoreBufferEmpty, g_hSemaphoreBufferFull;
生产者线程函数  
//unsigned int __stdcall ProducerThreadFun(PVOID pM)
//{
//	for (int i = 1; i <= END_PRODUCE_NUMBER; i++)
//	{
//		//等待有空的缓冲区出现  
//		WaitForSingleObject(g_hSemaphoreBufferEmpty, INFINITE);
//
//		//互斥的访问缓冲区  
//		EnterCriticalSection(&g_cs);
//		g_Buffer[g_i] = i;
//		printf("生产者在缓冲池第%d个缓冲区中投放数据%d\n", g_i, g_Buffer[g_i]);
//		g_i = (g_i + 1) % BUFFER_SIZE;
//		LeaveCriticalSection(&g_cs);
//
//		//通知消费者有新数据了  
//		ReleaseSemaphore(g_hSemaphoreBufferFull, 1, NULL);
//	}
//	printf("生产者完成任务,线程结束运行\n");
//	return 0;
//}
消费者线程函数  
//unsigned int __stdcall ConsumerThreadFun(PVOID pM)
//{
//	while (true)
//	{
//		//等待非空的缓冲区出现  
//		WaitForSingleObject(g_hSemaphoreBufferFull, INFINITE);
//
//		//互斥的访问缓冲区  
//		EnterCriticalSection(&g_cs);
//
//		printf("  编号为%d的消费者从缓冲池中第%d个缓冲区取出数据%d\n", GetCurrentThreadId(), g_j, g_Buffer[g_j]);
//		if (g_Buffer[g_j] == END_PRODUCE_NUMBER)//结束标志  
//		{
//			LeaveCriticalSection(&g_cs);
//			//通知其它消费者末尾的数据(结束标志)  
//			ReleaseSemaphore(g_hSemaphoreBufferFull, 1, NULL);//Full信号量++
//			 //不再移动缓冲池中的区块下标,因为已经取到了最后的一个数据
//			break;
//		}
//
//		g_j = (g_j + 1) % BUFFER_SIZE;//移动缓冲池中的区块下标,为了下次取数据
//		LeaveCriticalSection(&g_cs);
//
//
//		ReleaseSemaphore(g_hSemaphoreBufferEmpty, 1, NULL);//Empty信号量++
//	}
//
//	printf("  编号为%d的消费者收到通知,线程结束运行\n", GetCurrentThreadId());
//	return 0;
//}
//int main() {
//
//	InitializeCriticalSection(&g_cs);
//	//初始化信号量,一个记录有产品的缓冲区个数,另一个记录空缓冲区个数.  
//	g_hSemaphoreBufferEmpty = CreateSemaphore(NULL, 4, 4, NULL);//当前4个资源,最大允许4个同时访问 
//	g_hSemaphoreBufferFull = CreateSemaphore(NULL, 0, 4, NULL);//当前0个资源,最大允许4个同时访问 
//	g_i = 0;
//	g_j = 0;
//	memset(g_Buffer, 0, sizeof(g_Buffer));
//	const int THREADNUM = 3;
//	HANDLE hThread[THREADNUM];
//	//生产者线程  
//	hThread[0] = (HANDLE)_beginthreadex(NULL, 0, ProducerThreadFun, NULL, 0, NULL);
//	//消费者线程  
//	hThread[1] = (HANDLE)_beginthreadex(NULL, 0, ConsumerThreadFun, NULL, 0, NULL);
//	hThread[2] = (HANDLE)_beginthreadex(NULL, 0, ConsumerThreadFun, NULL, 0, NULL);
//	WaitForMultipleObjects(THREADNUM, hThread, TRUE, INFINITE);
//	for (int i = 0; i < THREADNUM; i++)
//		CloseHandle(hThread[i]);
//
//	//销毁信号量和关键段  
//	CloseHandle(g_hSemaphoreBufferEmpty);
//	CloseHandle(g_hSemaphoreBufferFull);
//	DeleteCriticalSection(&g_cs);
//	system("pause");
//	return 0;
//}


/情景3:/
2生产者 2消费者 4缓冲区  
//用一个信号量A来记录为空的缓冲区个数,另一个信号量B记录非空的缓冲区个数,
//然后生产者等待信号量A,消费者等待信号量B就可以了
//再使用一个关键段来控制缓冲区的访问

//#include <stdio.h>  
//#include <process.h>  
//#include <windows.h>
//volatile BOOL ProRun;              //生产者线程控制标志
//volatile int iData;				   //产品的标注
//const int END_PRODUCE_NUMBER = 8;  //生产产品个数  
//const int BUFFER_SIZE = 4;         //缓冲区个数  
//int g_Buffer[BUFFER_SIZE];         //缓冲池  
//int g_i, g_j;
信号量与关键段  
//CRITICAL_SECTION g_cs;
//HANDLE g_hSemaphoreBufferEmpty, g_hSemaphoreBufferFull;
//
设置控制台输出颜色  
//BOOL SetConsoleColor(WORD wAttributes)
//{
//	HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
//	if (hConsole == INVALID_HANDLE_VALUE)
//		return FALSE;
//
//	return SetConsoleTextAttribute(hConsole, wAttributes);
//}
//
生产者线程函数  
//unsigned int __stdcall ProducerThreadFun(PVOID pM)
//{
//	while (ProRun)
//	{
//		//等待有空的缓冲区出现  
//		WaitForSingleObject(g_hSemaphoreBufferEmpty, INFINITE);
//
//		//互斥的访问缓冲区  
//		EnterCriticalSection(&g_cs);
//		iData++;
//		if (iData > END_PRODUCE_NUMBER)//结束标志,所有数据已经生产完毕
//		{
//			ProRun = FALSE;//通知其他生产者结束线程
//			LeaveCriticalSection(&g_cs);
//			break;
//		}
//		else
//		{
//			g_Buffer[g_i] = iData;
//			printf("编号为%d的生产者在缓冲池第%d个缓冲区中投放数据%d\n", GetCurrentThreadId(), g_i, g_Buffer[g_i]);
//			g_i = (g_i + 1) % BUFFER_SIZE;
//			LeaveCriticalSection(&g_cs);
//			//通知消费者有新数据了  
//			ReleaseSemaphore(g_hSemaphoreBufferFull, 1, NULL);
//		}
//	}
//
//	printf("编号为%d生产者完成任务,线程结束运行\n", GetCurrentThreadId());
//	return 0;
//}
//
消费者线程函数  
//unsigned int __stdcall ConsumerThreadFun(PVOID pM)
//{
//	while (true)
//	{
//		//等待非空的缓冲区出现  
//		WaitForSingleObject(g_hSemaphoreBufferFull, INFINITE);
//
//		//互斥的访问缓冲区  
//		EnterCriticalSection(&g_cs);
//		SetConsoleColor(FOREGROUND_GREEN);
//		printf("  编号为%d的消费者从缓冲池中第%d个缓冲区取出数据%d\n", GetCurrentThreadId(), g_j, g_Buffer[g_j]);
//		SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN| FOREGROUND_BLUE);
//		if (g_Buffer[g_j] == END_PRODUCE_NUMBER)//结束标志  
//		{
//			LeaveCriticalSection(&g_cs);
//			//通知其它消费者末尾的数据(结束标志)  
//			ReleaseSemaphore(g_hSemaphoreBufferFull, 1, NULL);//Full信号量++
//															  //不再移动缓冲池中的区块下标,因为已经取到了最后的一个数据
//			break;
//		}
//
//		g_j = (g_j + 1) % BUFFER_SIZE;//移动缓冲池中的区块下标,为了下次取数据
//		LeaveCriticalSection(&g_cs);
//
//
//		ReleaseSemaphore(g_hSemaphoreBufferEmpty, 1, NULL);//Empty信号量++
//	}
//	SetConsoleColor(FOREGROUND_GREEN);
//	printf("  编号为%d的消费者收到通知,线程结束运行\n", GetCurrentThreadId());
//	SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
//	return 0;
//}
//int main() {
//
//	InitializeCriticalSection(&g_cs);
//	//初始化信号量,一个记录有产品的缓冲区个数,另一个记录空缓冲区个数.  
//	g_hSemaphoreBufferEmpty = CreateSemaphore(NULL, 4, 4, NULL);//当前4个资源,最大允许4个同时访问 
//	g_hSemaphoreBufferFull = CreateSemaphore(NULL, 0, 4, NULL);//当前0个资源,最大允许4个同时访问
//	ProRun = TRUE;
//	iData = 0;
//	g_i = 0;
//	g_j = 0;
//
//	memset(g_Buffer, 0, sizeof(g_Buffer));
//	const int THREADNUM = 4;
//	HANDLE hThread[THREADNUM];
//	//生产者线程  
//	hThread[0] = (HANDLE)_beginthreadex(NULL, 0, ProducerThreadFun, NULL, 0, NULL);
//	hThread[1] = (HANDLE)_beginthreadex(NULL, 0, ProducerThreadFun, NULL, 0, NULL);
//	//消费者线程  
//	hThread[2] = (HANDLE)_beginthreadex(NULL, 0, ConsumerThreadFun, NULL, 0, NULL);
//	hThread[3] = (HANDLE)_beginthreadex(NULL, 0, ConsumerThreadFun, NULL, 0, NULL);
//	WaitForMultipleObjects(THREADNUM, hThread, TRUE, INFINITE);
//	for (int i = 0; i < THREADNUM; i++)
//		CloseHandle(hThread[i]);
//
//	//销毁信号量和关键段  
//	CloseHandle(g_hSemaphoreBufferEmpty);
//	CloseHandle(g_hSemaphoreBufferFull);
//	DeleteCriticalSection(&g_cs);
//	system("pause");
//	return 0;
//}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值