生产者消费者问题是操作系统非常经典的一个问题,
问题描述:考虑有一些生产者和消费者进程,生产者进程生产信息并把它们放入缓冲池中,消费者从缓冲池中取走信息。生产者—消费者问题是相互合作的进程关系的一种抽象,如在输入时,输入进程是生产者,计算进程是消费者;而在输出时,则计算进程是生产者,打印进程是消费者。请使用信号量机制来解决生产者—消费者问题。
生产者消费者问题的重点是:
1生产者只有在缓冲池有空的时候才能去填充,否则只能等待
2消费者只有在缓冲池中有数据的时候才能消费数据,否则只能等待。
3由于存在多个生产者消费者线程,为了不产生幽灵数据,对缓冲池的操作必须是互斥的
4 生产者和消费者线程中的P V操作的顺序必须慎重考虑,否则会产生死锁
windows 提供了常用的互斥量(mutex)和信号量(Semaphore)两种数据结构
常用的操作有CreateSemaphore()、OpenSemaphore()、ReleaseSemaphore()、WaitForSingleObject()和WaitForMultipleObjects()等函数
CreateSemaphore()用来生成信号量可以指明信号量的大小初始值
WaitForSingleObject()用于消费信号量使得信号量减一
ReleaseSemaphore()将是信号量加一(可指定)
对于互斥量的操作也有一组操作
CreateMutex()生成一个互斥量
WaitForSingleObject()等待互斥量
ReleaseMutex()释放互斥量
生产者消费者的示例程序如下
// procom.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<iostream>
#include<Windows.h>
using namespace std;
const int BUFFER_SIZE = 5;
const int producerCount = 10;
const int consumerCount = 10;
const int timewait = INFINITE;
static int pID = 0;
int cID = 0;
HANDLE mutex;
HANDLE empty;
HANDLE full;
int in =0,out=0;
int buffer[BUFFER_SIZE];
DWORD WINAPI pFunc(LPVOID lparam);
DWORD WINAPI cFunc(LPVOID lparam);
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE pThread[producerCount];
HANDLE cThread[consumerCount];
DWORD producerID[producerCount];
DWORD consumerID[consumerCount];
mutex = CreateMutex(NULL,FALSE,NULL);
empty = CreateSemaphore(NULL,BUFFER_SIZE,BUFFER_SIZE,NULL);
full = CreateSemaphore(NULL,0,BUFFER_SIZE,NULL);
for(int i =0;i<producerCount;++i)
{
pThread[i] = CreateThread(NULL,0,pFunc,NULL,0,&producerID[i]);
if(NULL == pThread[i])
{
return -1;
}
}
for(int i=0;i<consumerCount;i++)
{
cThread[i] = CreateThread(NULL,0,cFunc,NULL,0,&consumerID[i]);
if(NULL ==cThread[i])
return -1;
}
int a;
cin>>a;
for(int i=0;i<producerCount;i++)
CloseHandle(pThread[i]);
for (int i=0;i<consumerCount;i++)
CloseHandle(cThread[i]);
CloseHandle(mutex);
CloseHandle(full);
CloseHandle(empty);
return 0;
}
DWORD WINAPI pFunc(LPVOID lparam)
{
Sleep(100);
WaitForSingleObject(empty,timewait);
WaitForSingleObject(mutex,timewait);
cout<<"produced by :"<<pID<<"in buffer pos " <<in<<endl;
buffer[in]=pID;
pID++;
in = (in +1)%BUFFER_SIZE;
ReleaseMutex(mutex);
ReleaseSemaphore(full,1,NULL);
return 0;
}
DWORD WINAPI cFunc(LPVOID lparam)
{
Sleep(100);
WaitForSingleObject(full,timewait);
WaitForSingleObject(mutex,timewait);
cID=buffer[out];
cout<<"consumed one ID:"<<cID<< " on buffer pos "<<out<<endl;
out=(out+1)%BUFFER_SIZE;
ReleaseMutex(mutex);
ReleaseSemaphore(empty,1,NULL);
return 0;
}
本文的程序以及概念参考如下
http://blog.csdn.net/wangweitingaabbcc/article/details/6833265
http://www.cnblogs.com/P_Chou/archive/2012/07/13/semaphore-and-mutex-in-thread-sync.html
http://blog.chinaunix.net/uid-26779539-id-3233615.html