使用事件和互斥量解决线程同步问题的经典问题——生产者和消费者问题
    创建2个线程,生产者线程和消费者线程。
    生产者线程负责生产产品,1次生产1个产品,生产的产品放入缓冲区,当缓冲区满了时,生产者暂停生产,等待消费者消费缓冲区中的产品再重新启动。因此,生产者生产产品前,需要等待缓冲区不满的消息。
    消费者线程负责消费缓冲区中的产品,1次消费1个产品,当缓冲区为空时,消费者暂停消费,等生产者向缓冲区中放入新的产品后再重新启动。因此,消费者消费产品之前,需要等待缓冲区不为空的消息。
    由于生产和消费时都会对缓冲区进行操作,因此,添加互斥量对线程进行互斥保护。

    VC6.0下的C++代码如下:

#include <windows.h>
#include
<stdio.h>

#define MAXPRODUCTCNT 100 // Max product Count
#define BUFSIZE 4 // product buffer size
HANDLE g_hThreads[
2]; //Thread handles, Produce thread and consume thread
HANDLE g_hNotFullEvent = NULL; // Product buffer is not full event
HANDLE g_hNotEmptyEvent = NULL; // product buffer is not empty event
HANDLE g_hMutex = NULL; // Mutex
int g_iStorageCnt = 0; // product count in buffer
int g_iProductIdx = 0; // Index of the last produced product
int g_iConsumeIdx = 0; // Index of the last consumed product


DWORD WINAPI ProduceThreadProc(LPVOID lpParam)
{
DWORD dwWaitResult
= 0;

// two objects.
// Mutex and Not full event.
HANDLE hObjects[2] = {NULL, NULL};
hObjects[
0] = g_hMutex;
hObjects[
1] = g_hNotFullEvent;

for (int iIdx = 0; iIdx < MAXPRODUCTCNT; iIdx++)
{
//Wait till Mutex and Not full event are set signaled.
dwWaitResult = WaitForMultipleObjects(
2, // number of handles in array
hObjects, // array of handles
TRUE, // wait till all are signaled
INFINITE); // indefinite wait
if (WAIT_OBJECT_0 != dwWaitResult)
{
printf(
"Wait error: (%d)\n", GetLastError());
ExitThread(
0);
}

// Create a Product
g_iProductIdx++;
g_iStorageCnt
++;
printf(
"Create Product %d\n", g_iProductIdx);

// check whether product buffer is full
if (g_iStorageCnt >= BUFSIZE)
{
if (!ResetEvent(g_hNotFullEvent) )
{
printf(
"SetEvent failed (%d)\n", GetLastError());
ExitThread(
0);
}
}

// set not empty event signaled.
if (!SetEvent(g_hNotEmptyEvent) )
{
printf(
"SetEvent failed (%d)\n", GetLastError());
ExitThread(
0);
}

// Release mutex
ReleaseMutex(g_hMutex);
}

return 1;
}

DWORD WINAPI ConsumeThreadProc(LPVOID lpParam)
{
DWORD dwWaitResult
= 0;

// two objects.
// Mutex and Not empty event.
HANDLE hObjects[2] = {NULL, NULL};
hObjects[
0] = g_hMutex;
hObjects[
1] = g_hNotEmptyEvent;


for (int iIdx = 0; iIdx < MAXPRODUCTCNT; iIdx++)
{
//Wait till Mutex and Not empty event are set signaled.
dwWaitResult = WaitForMultipleObjects(
2, // number of handles in array
hObjects, // array of handles
TRUE, // wait till all are signaled
INFINITE); // indefinite wait
if (WAIT_OBJECT_0 != dwWaitResult)
{
printf(
"Wait error: (%d)\n", GetLastError());
ExitThread(
0);
}

// Consume a Product
g_iStorageCnt--;
g_iConsumeIdx
++;
printf(
"Consume product %d(%d)\n", g_iConsumeIdx, g_iProductIdx);

// check whether product buffer is empty
if (g_iStorageCnt < 1)
{
if (!ResetEvent(g_hNotEmptyEvent) )
{
printf(
"SetEvent failed (%d)\n", GetLastError());
ExitThread(
0);
}
}

/*set not full event signaled*/
if (!SetEvent(g_hNotFullEvent) )
{
printf(
"SetEvent failed (%d)\n", GetLastError());
ExitThread(
0);
}

//Release mutex
ReleaseMutex(g_hMutex);

}

return 1;
}

void main()
{
DWORD dwThreadID[
2] = {0, 0};

// Create a manual-reset event object.
// set this to signaled when the product buffer is not empty.
g_hNotEmptyEvent = CreateEvent(
NULL,
// default security attributes
TRUE, // manual-reset event
FALSE, // initial state is nonsignaled
NULL // unnamed Event
);
if (NULL == g_hNotEmptyEvent)
{
printf(
"CreateEvent failed (%d)\n", GetLastError());
return;
}

// Create a manual-reset event object.
// set this to signaled when the product buffer is not full.
g_hNotFullEvent = CreateEvent(
NULL,
// default security attributes
TRUE, // manual-reset event
TRUE, // initial state is signaled
NULL // unnamed Event
);
if (NULL == g_hNotFullEvent)
{
printf(
"CreateEvent failed (%d)\n", GetLastError());
return;
}


// Create a mutex with no initial owner
g_hMutex = CreateMutex(
NULL,
// default security attributes
FALSE, // initially not owned
NULL); // unnamed mutex
if (NULL == g_hMutex)
{
printf(
"CreateMutex error: (%d)\n", GetLastError());
return;
}

// Create a thread to produce products.
g_hThreads[0] = CreateThread(NULL,
0,
ProduceThreadProc,
NULL,
0,
&dwThreadID[0]);
if (NULL == g_hThreads[0])
{
printf(
"CreateThread failed (%d)\n", GetLastError());
return;
}

// Create a thred to consume products.
g_hThreads[1] = CreateThread(NULL,
0,
ConsumeThreadProc,
NULL,
0,
&dwThreadID[1]);

if (g_hThreads[1] == NULL)
{
printf(
"CreateThread failed (%d)\n", GetLastError());
return;
}


DWORD dwWaitResult
= WaitForMultipleObjects(
2, // number of handles in array
g_hThreads, // array of thread handles
TRUE, // wait till all threads quit
INFINITE); // indefinite wait
if (WAIT_OBJECT_0 != dwWaitResult)
{
printf(
"Wait error : (%d)\n", GetLastError());
return;
}

CloseHandle(g_hThreads[
0]);
CloseHandle(g_hThreads[
1]);
CloseHandle(g_hNotFullEvent);
CloseHandle(g_hNotEmptyEvent);
CloseHandle(g_hMutex);


}
posted on 2011-06-28 15:37  闲云鹤  阅读(3152)  评论(0编辑  收藏  举报