多執行緒之生產者消費者

飛翔的黃瓜發表於2017-08-21

看了別人寫的多執行緒例子,自己也寫了一個,貼上了防止以後忘記

此例子有2個生產者,4個消費者,4個緩衝區,共生產12件商品

#include "stdafx.h"
#include <stdio.h>  
#include <process.h>  
#include <windows.h>
HANDLE g_hEventBufferFull,g_hEventBufferEmpty;
CRITICAL_SECTION g_cs;
const int Product_Num=12;//12件商品
const int Buffer_Size=4;//4個緩衝區
int Buffer[Buffer_Size];
int j=0;//生產者正在用的緩衝區
int k=0;//消費者正在用的緩衝區
int i=1;//已生成商品數量,同時代表每個商品的內容
bool gBuffer=false;
unsigned int __stdcall ProductFun(PVOID pM)
{
	while(i<=Product_Num)
	{
		WaitForSingleObject(g_hEventBufferFull,INFINITE);
		EnterCriticalSection(&g_cs);
		if(Product_Num<i)//這裡生產者緩衝區一直會多執行一次到13,大概是
			              //因為上一個執行緒i++到13.而第二個執行緒已經在迴圈內,所以為13
						  //g_hEventBufferFull在消費者正常結束下是大於0的,所以出現資料
						  //為13的情況,所以特加此判斷
		{
			LeaveCriticalSection(&g_cs);
			ReleaseSemaphore(g_hEventBufferEmpty,1,NULL);
			break;
		}
		Buffer[j]=i;
		printf("編號為%d的生產者在緩衝區%d中投放資料%d\n",GetCurrentThreadId(),j,Buffer[j]);
			j=(j+1)%Buffer_Size;
			i++;
			Sleep(50);//Sleep是為了給其他的執行緒騰出一些時間,充分體現出亂序的特點。否則CPU的執行速度很快,
			           //很可能在其他執行緒剛剛開啟,當前執行緒已經執行完了,造成執行緒有序執行的假象。
			LeaveCriticalSection(&g_cs);
			ReleaseSemaphore(g_hEventBufferEmpty,1,NULL); 
	}
	printf("生產者%d完成任務,執行緒結束執行\n",GetCurrentThreadId()); 
	return 0; 

}
unsigned int __stdcall ConsumerFun(PVOID pM)
{
	while(true)
	{
	    WaitForSingleObject(g_hEventBufferEmpty,INFINITE);
		EnterCriticalSection(&g_cs);
		if(true==gBuffer)
		{
			break;
		}
		printf("    編號為%d的Consumer在緩衝區%d中取走資料%d\n",GetCurrentThreadId(),k,Buffer[k]);
		if(Buffer[k]==Product_Num)//這裡的本意是為了結束另一個執行緒,不造成死鎖,但造成了消費重複,所以在
			                      //上邊加了一個判斷
		{
			LeaveCriticalSection(&g_cs); 
				ReleaseSemaphore(g_hEventBufferEmpty,1,NULL);
				gBuffer=true;
				break;
		}
		k=(k+1)%Buffer_Size;
		Sleep(50);
		LeaveCriticalSection(&g_cs); 
		ReleaseSemaphore(g_hEventBufferFull,1,NULL);
	}
	 printf("    編號為%d的消費者收到通知,執行緒結束執行\n", GetCurrentThreadId());  
	 return 0; 
}
int main()
{
	printf("生產者消費者問題by ShallWe\n");
	InitializeCriticalSection(&g_cs);
	g_hEventBufferFull=CreateSemaphore(NULL,4,4,NULL);
	g_hEventBufferEmpty=CreateSemaphore(NULL,0,4,NULL);
	HANDLE Thread[4];
	memset(Buffer,0,sizeof(Buffer));
	Thread[0]=(HANDLE)_beginthreadex(NULL,0,ProductFun,NULL,0,NULL);
	Thread[1]=(HANDLE)_beginthreadex(NULL,0,ProductFun,NULL,0,NULL);
	Thread[2]=(HANDLE)_beginthreadex(NULL,0,ConsumerFun,NULL,0,NULL);
	Thread[3]=(HANDLE)_beginthreadex(NULL,0,ConsumerFun,NULL,0,NULL);
	WaitForMultipleObjects(4, Thread, TRUE, INFINITE);
	    for (int i = 0; i < 4; i++)  
        CloseHandle(Thread[i]);  
  
    //銷燬訊號量和關鍵段  
    CloseHandle(g_hEventBufferFull);  
    CloseHandle(g_hEventBufferEmpty);  
    DeleteCriticalSection(&g_cs);  
	system("pause");
	return 0;

}


相關文章