生产者消费者问题: 该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。具体我就不解释了 应该都懂 不懂请百度一下
我是用事件实现生产者消费者问题的同步 用临界区实现互斥 我的这个做法与经典做法不同 即用信号量的做法! 经典做法为法二
法一:
具体看代码:
#include
#include
#include
int vol = 2;//缓冲区容量
int *g_pBuffer, g_BufferOff = 0, count;//依次为缓冲区,指向当前产品存放的位置, 目前缓冲区中产品数量
HANDLE g_ProducerEvent, g_ConsumerEvent;
CRITICAL_SECTION g_cs;//临界区
int ProNum = 10;//要生产的产品数量
int HasProduced = 0;//已经生产的个数
int HasConsumerd = 0;//已经消费的个数
unsigned int __stdcall FunPro(PVOID Pv)//生产者
{
int k = *(int *)Pv;//生产者编号
while(1)
{
WaitForSingleObject(g_ProducerEvent, INFINITE);//等待生产者获取运行权限
EnterCriticalSection(&g_cs);//申请临界区
if(count < vol)//缓冲区未满
{
if(count == 0)//如果当前有0个产品
{
SetEvent(g_ProducerEvent);//让生产者运行
ResetEvent(g_ConsumerEvent);//阻止消费者运行
}
else
{
SetEvent(g_ProducerEvent);//如果有多个产品 且缓冲区没满
SetEvent(g_ConsumerEvent); //让2者均可以运行
}
if(HasProduced >= ProNum)//生产的产品个数已经达到就不再生产了
{
LeaveCriticalSection(&g_cs);
break;
}
count++;//生产了一个产品 当前产品数加1
HasProduced++;//已经生产国多少个产品了 包括已经消费的
g_BufferOff = (g_BufferOff + 1) % vol;//当前生产的产品要存储的位置
g_pBuffer[g_BufferOff] = HasProduced;
printf("生产者 %d 生产出一个产品,编号为 %d 存储位置%d 共有产品%d个 \n",k, HasProduced, g_BufferOff, count);
Sleep(10);
}
else//缓冲区已满
{
ResetEvent(g_ProducerEvent);// 阻止生产者运行
SetEvent(g_ConsumerEvent);// 让消费者运行
Sleep(10);//
}
LeaveCriticalSection(&g_cs);//释放临界区
}
return 0;
}
unsigned int __stdcall FunCon(PVOID Pv)
{
int k = *(int *)Pv;//消费者编号
while(1)
{
WaitForSingleObject(g_ConsumerEvent, INFINITE);//等待消费者获取运行权限
EnterCriticalSection(&g_cs);//进入临界区
if(count > 0)//如果当前有产品
{
if(count == vol)//如果缓冲区已满
{
ResetEvent(g_ProducerEvent);//让生产者不再运行
SetEvent(g_ConsumerEvent);//让消费者赶紧运行消费
}
else//如果缓冲区不满 则设置2者均可运行
{
SetEvent(g_ProducerEvent);
SetEvent(g_ConsumerEvent);
}
if(HasConsumerd>= ProNum)//如果已经消费的数量达到了要求的总产品数量 就不再消费 别忘记释放临界区!
{
LeaveCriticalSection(&g_cs);
break;
}
printf("消费者%d消费了一个产品 编号为%d 它存放在坐标%d 还剩产品%d个\n", k, g_pBuffer[g_BufferOff], g_BufferOff, count - 1);
count--;
HasConsumerd++;
g_BufferOff = (g_BufferOff - 1 + 10) % vol;
Sleep(100);
}
else//当前无产品
{
ResetEvent(g_ConsumerEvent);
SetEvent(g_ProducerEvent);
Sleep(100);
}
LeaveCriticalSection(&g_cs);
}
return 0;
}
int main()
{
HANDLE Producer1, Producer2, Producer3, Consumer, Consumer2;
g_BufferOff = -1;
count = 0;
g_pBuffer = new int [vol];
int k1 = 1, k2 = 2, k3 = 3, t1 = 1, t2 = 2;
//初始化临界区 创建事件 创建线程
InitializeCriticalSection(&g_cs);
g_ProducerEvent = CreateEvent(NULL, TRUE, TRUE, "Producer");
g_ConsumerEvent = CreateEvent(NULL, TRUE, FALSE, "Consumer");
Producer1 = (HANDLE)_beginthreadex(NULL, 0, FunPro, &k1, 0, NULL);
Producer2 = (HANDLE)_beginthreadex(NULL, 0, FunPro, &k2, 0, NULL);
Producer3 = (HANDLE)_beginthreadex(NULL, 0, FunPro, &k3, 0, NULL);
Consumer = (HANDLE)_beginthreadex(NULL, 0, FunCon, &t1, 0, NULL);
Consumer2 = (HANDLE)_beginthreadex(NULL, 0, FunCon, &t2, 0, NULL);
Sleep(15000000);
//以下全是销毁工作
CloseHandle(g_ConsumerEvent);
CloseHandle(g_ProducerEvent);
CloseHandle(Producer1);
CloseHandle(Producer2);
CloseHandle(Producer3);
CloseHandle(Consumer);
CloseHandle(Consumer2);
delete []g_pBuffer;
DeleteCriticalSection(&g_cs);
system("pause");
return 0;
}
法二:
#include
#include
#include
int g_vol = 10;//缓冲区容量
int *g_pBuffer, g_BufferOff = -1, count;//依次为缓冲区,指向当前产品存放的位置, 目前缓冲区中产品数量
HANDLE g_hSemaphoreFull, g_hSemaphoreEmpty;//缓冲区已用位置信号量 未用位置信号量句柄
CRITICAL_SECTION g_cs;//临界区
int g_ProNum = 20;//要生产的产品数量
int g_HasProduced = 0;//已经生产了的产品数量
int g_HasConsumerd = 0;
unsigned int __stdcall FunPro(PVOID Pv)//生产者
{
int k = *(int *)Pv;//生产者编号
while(1)
{
WaitForSingleObject(g_hSemaphoreEmpty, INFINITE);
EnterCriticalSection(&g_cs);
if(g_HasProduced >= g_ProNum) break;
g_HasProduced++;//已经生产国多少个产品了 包括已经消费的
g_BufferOff = (g_BufferOff + 1) % g_vol;//当前生产的产品要存储的位置
g_pBuffer[g_BufferOff] = g_HasProduced;
printf("生产者 %d 生产出一个产品,编号为 %d 存储位置%d \n",k, g_HasProduced, g_BufferOff);
ReleaseSemaphore(g_hSemaphoreFull, 1, NULL);//将Full信号量+1 表示已经有了一个产品
LeaveCriticalSection(&g_cs);
Sleep(10);
}
return 0;
}
unsigned int __stdcall FunCon(PVOID Pv)
{
int k = *(int *)Pv;//消费者编号
while(1)
{
WaitForSingleObject(g_hSemaphoreFull, INFINITE);
EnterCriticalSection(&g_cs);
if(g_HasConsumerd >= g_ProNum) break;
printf("消费者%d消费了一个产品 编号为%d 它存放在坐标%d \n", k, g_pBuffer[g_BufferOff], g_BufferOff);
count--;
g_HasConsumerd++;
g_BufferOff = (g_BufferOff - 1 + 10) % g_vol;
ReleaseSemaphore(g_hSemaphoreEmpty, 1, NULL);
LeaveCriticalSection(&g_cs);
Sleep(100);
}
return 0;
}
int main()
{
HANDLE Producer1, Producer2, Producer3, Consumer, Consumer2;
g_BufferOff = -1;
count = 0;
g_pBuffer = new int [g_vol];
int k1 = 1, k2 = 2, k3 = 3, t1 = 1, t2 = 2;
//初始化临界区 创建事件 创建线程
InitializeCriticalSection(&g_cs);
g_hSemaphoreFull = CreateSemaphore(NULL, 0 , 100, "Full");//创建信号量 初始资源数量为0 最大并发数量我设置的100
g_hSemaphoreEmpty = CreateSemaphore(NULL, g_vol, 100, "Empty");
Producer1 = (HANDLE)_beginthreadex(NULL, 0, FunPro, &k1, 0, NULL);
Producer2 = (HANDLE)_beginthreadex(NULL, 0, FunPro, &k2, 0, NULL);
Producer3 = (HANDLE)_beginthreadex(NULL, 0, FunPro, &k3, 0, NULL);
Consumer = (HANDLE)_beginthreadex(NULL, 0, FunCon, &t1, 0, NULL);
Consumer2 = (HANDLE)_beginthreadex(NULL, 0, FunCon, &t2, 0, NULL);
Sleep(15000000);
//以下全是销毁工作
CloseHandle(g_hSemaphoreFull);
CloseHandle(g_hSemaphoreEmpty);
CloseHandle(Producer1);
CloseHandle(Producer2);
CloseHandle(Producer3);
CloseHandle(Consumer);
CloseHandle(Consumer2);
delete []g_pBuffer;
DeleteCriticalSection(&g_cs);
system("pause");
return 0;
}