生产者消费者问题是操作系统非常经典的一个问题,
问题描述:考虑有一些生产者和消费者进程,生产者进程生产信息并把它们放入缓冲池中,消费者从缓冲池中取走信息。生产者—消费者问题是相互合作的进程关系的一种抽象,如在输入时,输入进程是生产者,计算进程是消费者;而在输出时,则计算进程是生产者,打印进程是消费者。请使用信号量机制来解决生产者—消费者问题。
生产者消费者问题的重点是:
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