多线程之生产者消费者

来源:互联网 发布:淘宝店铺如何转让 编辑:程序博客网 时间:2024/05/01 21:09

看了别人写的多线程例子,自己也写了一个,贴上了防止以后忘记

此例子有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;}