/*
生产者与消费者问题的实现。
创建一组“生产者”线程和一组“消费者”线程,并建立一个长度为N的缓冲池。
“生产者”向缓冲区输入数据,“消费者”从缓冲区读出数据。
当缓冲区满时,“生产者”必须阻塞,等待“消费者”取走缓冲区数据后将其唤醒。
当缓冲区空时,“消费者”阻塞,等待“生产者”生产了产品后将其唤醒。
用信号量实现“生产者”与“消费者”线程之间的同步。
*/
#include <windows.h>
#include <iostream>
#include<cstdio>
const int PCOUNT = 5; //生产者的个数
const int CCOUNT = 5; //消费者的个数
const int N = 8; //缓冲池中缓冲区数量
int ProductID = 0; //生产产品号
int ConsumeID = 0; //消费产品号
int in = 0;
int out = 0;
int total = 0; //库存量
int Buffer[N]; //缓冲池
int buffer[N];
bool stop = false;
HANDLE Mutex; //互斥信号量实现缓冲池的互斥使用
HANDLE Full; //缓冲池中满缓冲区的数量
HANDLE Empty; //缓冲池中空缓冲区的数量
SYSTEMTIME systime;
DWORD WINAPI Producer(LPVOID); //生产者线程
DWORD WINAPI Consumer(LPVOID); //消费者线程
int main()
{
//创建各个互斥信号
Mutex = CreateMutex(NULL,FALSE,NULL);
Full = CreateSemaphore(NULL,N-1,N-1,NULL);
Empty = CreateSemaphore(NULL,0,N-1,NULL);
//创建互斥信号量失败
if (Mutex == NULL)
{
printf("CreateMutex error: %d\n", GetLastError());
return 0;
}
//创建Full信号量失败
if (Full == NULL)
{
printf("CreateSemaphoreFull error: %d\n", GetLastError());
return 0;
}
//创建Empty信号量失败
if (Empty == NULL)
{
printf("CreateSemaphoreEmpty error: %d\n", GetLastError());
return 0;
}
HANDLE ProducerThreads[PCOUNT]; //生产者线程
HANDLE ConsumerThreads[CCOUNT]; //消费者线程
DWORD producerID[PCOUNT]; //生产者线程的标识符
DWORD consumerID[CCOUNT]; //消费者线程的标识符
//创建生产者线程
for (int i=0;i<PCOUNT;++i)
{
ProducerThreads[i]=CreateThread(NULL,0,Producer,NULL,0,&producerID[i]);
if(ProducerThreads[i] == NULL )
{
printf("CreateThread error: %d\n", GetLastError());
return 0;
}
}
//创建消费者线程
for (i=0;i<CCOUNT;++i)
{
ConsumerThreads[i]=CreateThread(NULL,0,Consumer,NULL,0,&consumerID[i]);
if( ConsumerThreads[i] == NULL)
{
printf("CreateThread error: %d\n", GetLastError());
return 0;
}
}
while(!stop)
{
if(getchar())//按回车后终止程序运行
{
stop = true;
}
}
return 0;
}
//生产
void Produce()
{
printf("生产第%d个产品并加入库存中\n",++ProductID );
Buffer[in] = 1;
in = (in+1)%N;
//输出缓冲区当前的状态
printf("缓冲区当前的状态:");
for (int i=0;i<N;++i)
{
printf("%d",Buffer[i]);
}
printf("\n");
printf("生产者ID:%d\n",GetCurrentThreadId());
buffer[in-1] = GetCurrentThreadId();
printf("产品ID:%d\t\t缓冲区ID:%d\n",ProductID,in);
GetLocalTime(&systime);
printf("时间:%02d:%02d:%02d\t\t", systime.wHour, systime.wMinute, systime.wSecond);
printf("当前库存量:%d\n",++total);
printf("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
}
//消费
void Consume()
{
printf("消费第%d个产品并从库存拿出\n",++ConsumeID);
Buffer[out] = 0;
out = (out+1)%N;
//输出缓冲区当前的状态
printf("缓冲区当前的状态:");
for (int i=0;i<N;++i)
{
printf("%d",Buffer[i]);
}
printf("\n");
printf("消费者ID:%d\n",GetCurrentThreadId());
printf("产品ID:%d\t\t缓冲区ID:%d\t\t来自生产者ID:%d\n",ConsumeID,out,buffer[out-1]);
GetLocalTime(&systime);
printf("时间:%02d:%02d:%02d\t\t", systime.wHour, systime.wMinute, systime.wSecond);
printf("当前库存量:%d\n",--total);
printf("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
}
//生产者
DWORD WINAPI Producer(LPVOID lpPara)
{
while(!stop)
{
WaitForSingleObject(Full,INFINITE);
WaitForSingleObject(Mutex,INFINITE);
Produce();
Sleep(1000);
ReleaseMutex(Mutex);
ReleaseSemaphore(Empty,1,NULL);
}
return 0;
}
//消费者
DWORD WINAPI Consumer(LPVOID lpPara)
{
while(!stop)
{
WaitForSingleObject(Empty,INFINITE);
WaitForSingleObject(Mutex,INFINITE);
Consume();
Sleep(1000);
ReleaseMutex(Mutex);
ReleaseSemaphore(Full,1,NULL);
}
return 0;
}