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

被折叠的 条评论
为什么被折叠?



