由于我喜欢用互斥器,因此这篇文章,我使用互斥器与信号量来解决消费者与生产者问题。对于信号量,互斥器的理解,请看《几段简单的文字教你秒懂事件,信号量,互斥器三大线程同步函数》我之前写代码的时候,单单就是用信号量来完成,觉得加了一个关键段费力,后来发现不行!至于为什么不行,其余秒杀多线程一文讲的很清楚了。你自己好好琢磨看看。好了,下面给出代码(对于输出颜色的代码,请看《利用SetConsoleTextAttribute函数设置控制台输出文字的颜色》):
#include "windows.h"
#include "stdio.h"
int ProductNum=8;
int BufferSize=4;
int Buffer[4];
int ProductPool,ConsumerPool;
HANDLE hSemaphoreEmpty,hSemaphoreFull;
HANDLE hMutex;
BOOL SetConsoleColor(WORD wAttributes)
{
HANDLE hConsole=GetStdHandle(STD_OUTPUT_HANDLE);
if(hConsole==INVALID_HANDLE_VALUE)
{
return false;
}
return SetConsoleTextAttribute(hConsole,wAttributes);
}
DWORD WINAPI ProducterFunc(LPVOID pm)
{
for(int i=1; i<=8; i++)
{
WaitForSingleObject(hSemaphoreEmpty,INFINITE);
WaitForSingleObject(hMutex,INFINITE);
Buffer[ProductPool]=i;
SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
printf("生产者在缓冲池第%d个缓冲区中投放数据%d\n", ProductPool, Buffer[ProductPool]);
ProductPool=(ProductPool+1)%4;
ReleaseSemaphore(hSemaphoreFull,1,NULL);
ReleaseMutex(hMutex);
}
printf("生产者完成任务,线程结束运行\n");
return 0;
}
DWORD WINAPI ConsumerFunc(LPVOID pm)
{
while(1)
{
WaitForSingleObject(hSemaphoreFull,INFINITE);
WaitForSingleObject(hMutex,INFINITE);
SetConsoleColor(FOREGROUND_GREEN);
printf("编号为%d的消费者从缓冲池中第%d个缓冲区取出数据%d\n", GetCurrentThreadId(), ConsumerPool, Buffer[ConsumerPool]);
if(Buffer[ConsumerPool]==8)
{
ReleaseSemaphore(hSemaphoreFull,1,NULL);
ReleaseMutex(hMutex);
break;
}
ConsumerPool=(ConsumerPool+1)%4;
//Sleep(500);
ReleaseSemaphore(hSemaphoreEmpty,1,NULL);
ReleaseMutex(hMutex);
}
printf("编号为%d的消费者收到通知,线程结束运行\n", GetCurrentThreadId());
return 0;
}
int main()
{
hSemaphoreEmpty=CreateSemaphore(NULL,4,4,NULL);
hSemaphoreFull=CreateSemaphore(NULL,0,4,NULL);
hMutex=CreateMutex(NULL,FALSE,NULL);
ProductPool=0;
ConsumerPool=0;
HANDLE handle[3];
memset(Buffer,0,sizeof(Buffer));
//生产者线程
handle[0]=CreateThread(NULL,0,ProducterFunc,NULL,0,NULL);
//消费者线程
handle[1]=CreateThread(NULL,0,ConsumerFunc,NULL,0,NULL);
handle[2]=CreateThread(NULL,0,ConsumerFunc,NULL,0,NULL);
WaitForMultipleObjects(3,handle,TRUE,INFINITE);
for(int i=0; i<3; i++)
{
CloseHandle(handle[i]);
}
CloseHandle(hSemaphoreEmpty);
CloseHandle(hSemaphoreFull);
CloseHandle(hMutex);
system("pause");
return 0;
}
运行图: