看了别人写的多线程例子,自己也写了一个,贴上了防止以后忘记
此例子有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;
}