多线程-生产者与消费者问题

本文通过两个实例详细介绍了生产者-消费者模型的实现方法。第一个实例为一个生产者、一个消费者和一个缓冲区的情况;第二个实例则拓展到一个生产者、多个消费者及多个缓冲区的场景。文中使用了Windows线程API进行多线程编程,并利用事件和信号量来同步生产者与消费者的操作。

参考http://blog.youkuaiyun.com/morewindows/article/details/7577591实现的简单例子


一个生产者、一个消费者、一个缓冲区

#include <stdio.h>
#include <process.h>
#include <windows.h>
#include <iostream>
using namespace std;

const int PRODUCE_NUMBER = 50;

int g_iHole;

HANDLE g_hEventHoleEmpty;		// 坑空事件 
HANDLE g_hEventHoleFull;		// 坑满事件 




unsigned int __stdcall uiProduceTread(void* p)
{
	int l_iShouldProduceNum = PRODUCE_NUMBER;
	while(l_iShouldProduceNum--)
	{
		WaitForSingleObject(g_hEventHoleEmpty, INFINITE);
		
		g_iHole = PRODUCE_NUMBER-l_iShouldProduceNum;
		
		printf("putin %d\n", g_iHole); 
		
		Sleep(10);
		
		SetEvent(g_hEventHoleFull);
	}
	
	return 0;
}


unsigned int __stdcall uiConsumeTread(void* p)
{
	int l_iConsumeCnt = 1;
	while(l_iConsumeCnt <= PRODUCE_NUMBER)
	{
		WaitForSingleObject(g_hEventHoleFull, INFINITE);		
		
		printf("---getout %d\n", g_iHole); 
		
		l_iConsumeCnt++;
		
		SetEvent(g_hEventHoleEmpty);			
	}
	

	
	return 0;
}


int main(int argc, char* argv[])
{
	
	g_hEventHoleFull 	= CreateEvent(NULL, FALSE, FALSE, NULL);  
	g_hEventHoleEmpty 	= CreateEvent(NULL, FALSE, TRUE, NULL);  
	 
	HANDLE handle1 = (HANDLE)_beginthreadex(NULL, 0, &uiProduceTread, NULL, 0, NULL);
	HANDLE handle2 = (HANDLE)_beginthreadex(NULL, 0, &uiConsumeTread, NULL, 0, NULL);
	
	HANDLE l_haHandleArray[2] = {handle1, handle2};
	
	cout << handle1 << endl << handle2 << endl << endl;
	WaitForMultipleObjects(2, l_haHandleArray, TRUE, INFINITE); 
	cout << handle1 << endl << handle2 << endl << endl;
		
	CloseHandle(handle1);  
    CloseHandle(handle2);  	
	
	CloseHandle(g_hEventHoleFull);  
    CloseHandle(g_hEventHoleEmpty);  
	
	return 0;
}





一个生产者、多个消费者、多个缓冲区

#include <iostream>
#include <windows.h>
using namespace std;


const int NUM_OF_PRODUCER 	= 1;	//生产者个数 
const int NUM_OF_CONSUMER 	= 2;	//消费者个数 
const int NUM_OF_HOLE 		= 4;	//坑个数 

const int NUM_OF_PRODUCT	= 10;	//要生产的产品个数 

HANDLE g_hHandles[NUM_OF_PRODUCER+NUM_OF_CONSUMER];		//线程句柄数组 

HANDLE g_hSemaphoreFull;				//表示坑满信号量 
HANDLE g_hSemaphoreEmpty;				//表示坑空信号量 

HANDLE g_hExitEvent;

int g_iaHole[NUM_OF_HOLE] = {0};	//坑数组 

CRITICAL_SECTION g_cs;				//关键段

void vInitHole(void)
{
	int i = 0;
	for(i=0; i<NUM_OF_HOLE; i++)
	{
		g_iaHole[i] = -1;
	}
}

int iIsHoleEmpty()
{
	int i = 0;
	for(i=0; i<NUM_OF_HOLE; i++)
	{
		if(-1 != g_iaHole[i])
		{
			return 0;
		}
	}
	return 1;
}

void vShowHole()
{
	int i = 0;
	printf("\t\tHOLE:");
	for(i=0; i<NUM_OF_HOLE; i++)
	{
		printf("%d\t", g_iaHole[i]);
	}
	printf("\n");	
}

int iProduce(DWORD p_dwThreadID, int* p_iSite, int* p_ProductID)
{
	int l_iResult = 0;
	static int l_siHoleSite = 0;
	
	EnterCriticalSection(&g_cs);
	if(-1 != g_iaHole[l_siHoleSite])
	{
		l_iResult = 1;
	}
	else
	{
		*p_iSite = l_siHoleSite;				//生产的产品存放的位置 
		*p_ProductID = *p_ProductID; 			//生产的产品 
		g_iaHole[l_siHoleSite] = *p_ProductID;	//生产 
		printf("Thread %d:Produce %d in %d\n", p_dwThreadID, *p_ProductID, l_siHoleSite);
		l_siHoleSite++;
		if(l_siHoleSite >= NUM_OF_HOLE)
		{
			l_siHoleSite = 0;
		}
		vShowHole(); 
		printf("\n"); 
	}
	LeaveCriticalSection(&g_cs);
	
	return l_iResult;
}

int iConsume(DWORD p_dwThreadID, int* p_iSite, int* p_ProductID)
{
	int l_iResult = 0;
	static int l_siHoleSite = 0;
	
	EnterCriticalSection(&g_cs);
	if(-1 == g_iaHole[l_siHoleSite])
	{
		l_iResult = 1;
	}
	else
	{
		*p_iSite = l_siHoleSite;				//消费的产品存放的位置 
		*p_ProductID = g_iaHole[l_siHoleSite];	//消费的产品 
		g_iaHole[l_siHoleSite] = -1;			//消费
		printf("Thread %d:consume %d in %d\n", p_dwThreadID, *p_ProductID, l_siHoleSite);
		l_siHoleSite++;
		if(l_siHoleSite >= NUM_OF_HOLE)
		{
			l_siHoleSite = 0;
		}	
		vShowHole();
		printf("\n"); 		
	}	
	LeaveCriticalSection(&g_cs);
	
	return l_iResult;	
}


unsigned int __stdcall uiProducerThread(void* p)
{
	int l_iProduceResult = 0;
	int l_iProductID = 0;
	int l_iProduceSite = 0;
	DWORD l_lThreadID = GetCurrentThreadId();
	
	HANDLE l_hProduceHandle[2] = {g_hSemaphoreEmpty, g_hExitEvent};
	
	while(l_iProductID < NUM_OF_PRODUCT)
	{
		DWORD l_dwObj = WaitForMultipleObjects(2, l_hProduceHandle, FALSE, INFINITE);	
		if(WAIT_OBJECT_0 == l_dwObj)											//坑空信号量有信号 
		{
			l_iProduceResult = iProduce(l_lThreadID, &l_iProduceSite, &l_iProductID);		//生产
			if(0 != l_iProduceResult)
			{
				printf("Producer Error!\n");
				SetEvent(g_hExitEvent);
			}
			ReleaseSemaphore(g_hSemaphoreFull, 1, NULL); 			
		}
		else if(WAIT_OBJECT_0+1 == l_dwObj)										//退出事件 
		{
			printf("Producer Exit!\n");
			break; 
		}
		else
		{}
		l_iProductID++;	
	}
	SetEvent(g_hExitEvent);
	return 0;
}

unsigned int __stdcall uiConsumerThread(void* p)
{
	int l_iConsumeResult = 0;
	int l_iProductID = 0;
	int l_iProduceSite = 0;
	DWORD l_lThreadID = GetCurrentThreadId();
	
	HANDLE l_hConsumeHandle[2] = {g_hSemaphoreFull, g_hExitEvent};

	while(l_iProductID < NUM_OF_PRODUCT)
	{
		DWORD l_dwObj = WaitForMultipleObjects(2, l_hConsumeHandle, FALSE, INFINITE);			
		if(WAIT_OBJECT_0 == l_dwObj) 											//坑满信号量有信号 
		{
			l_iConsumeResult = iConsume(l_lThreadID, &l_iProduceSite, &l_iProductID);		//消费
			
			if(0 != l_iConsumeResult) 
			{
				printf("Consumer Error!\n");
				SetEvent(g_hExitEvent);
			}
			ReleaseSemaphore(g_hSemaphoreEmpty, 1, NULL); 		
		}
		else if(WAIT_OBJECT_0+1 == l_dwObj)										//退出事件 
		{
			if(1 == iIsHoleEmpty())
			{
				break;
			} 
		}
		else
		{}
		

	}	
	return 0;
}



int main()
{
	int l_iProducerCnt = 0;
	int l_iConsumerCnt = 0;
	int l_iHandleCnt = 0;
	vInitHole();
	
	InitializeCriticalSection(&g_cs);
	
	g_hExitEvent		= CreateEvent( 	NULL,			// 安全控制,一般直接传入NULL。  
			                            TRUE,			// 确定事件是手动置位还是自动置位,传入TRUE表示手动置位,传入FALSE表示自动置位。  
			                            FALSE,			// 事件的初始状态,传入TRUE表示已触发。  
			                            NULL);			// 事件的名称,传入NULL表示匿名事件。
	
	g_hSemaphoreFull 	= CreateSemaphore(NULL, 0, NUM_OF_HOLE, NULL);				//表示坑满信号量 
	g_hSemaphoreEmpty 	= CreateSemaphore(NULL, NUM_OF_HOLE, NUM_OF_HOLE, NULL);	//表示坑空信号量 
	
	
	for(l_iProducerCnt=0; l_iProducerCnt<NUM_OF_PRODUCER; l_iProducerCnt++)
	{
		g_hHandles[l_iProducerCnt] = (HANDLE)_beginthreadex(NULL, 0, uiProducerThread, NULL, 0, NULL);	//生产者 
	}
	
	for(l_iConsumerCnt=0; l_iConsumerCnt<NUM_OF_CONSUMER; l_iConsumerCnt++)
	{
		g_hHandles[l_iProducerCnt+l_iConsumerCnt] = (HANDLE)_beginthreadex(NULL, 0, uiConsumerThread, NULL, 0, NULL);	//消费者
	} 

	WaitForMultipleObjects(NUM_OF_PRODUCER+NUM_OF_CONSUMER, g_hHandles, TRUE, INFINITE);
	
	DeleteCriticalSection(&g_cs);
	
	CloseHandle(g_hExitEvent);
	CloseHandle(g_hSemaphoreFull);
	CloseHandle(g_hSemaphoreEmpty);
	
	for(l_iHandleCnt=0; l_iHandleCnt<NUM_OF_PRODUCER+NUM_OF_CONSUMER; l_iHandleCnt++)
	{
		CloseHandle(g_hHandles[l_iHandleCnt]);	
	}

	return 0;
	
}









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值