之前的是单生产消费者 使用一个mutex解决生产者消费者问题
其中第2个例子使用了事件对象, 用于单线程的情况. 若在linux 上用信号量每次解锁一次即可;
如果要修改成多个的情况,就要使用信号量.
先解决多个生产 1个消费的问题:
const int BUFF_SIZE = 10; //缓冲区大小
const int NTIMES = 50; //总共生产的个数
static int producer_gcount = 0; //仅仅用于显示死锁问题
struct
{
HANDLE mutex;
HANDLE sem_empty; //修改成信号量, 可以用于多个线程同时访问
HANDLE sem_stored; //同上
int arr[BUFF_SIZE];
int index;
} share_object;
unsigned int WINAPI producer_thread( void* lpParameter)
{
while(1)
{
WaitForSingleObject(share_object.sem_empty,-1) ; //等待至少一个信号量
WaitForSingleObject(share_object.mutex,-1); //多个生产者必须互斥
if(share_object.index >= NTIMES){
//到这里说明全部生产完毕 .
//注意先释放信号量,否则如果线程数大于sem_empty的数量,将发生死锁
if(producer_gcount == 0){
++producer_gcount;
cout << "producer all done" << endl;
} else {
cout << " ******* other producer threads *****" << endl;
}
ReleaseSemaphore(share_object.sem_empty,1,0);
ReleaseMutex(share_object.mutex);
break;
}
//到这里说明继续生产
share_object.arr[share_object.index++ % BUFF_SIZE] = 1;
ReleaseMutex(share_object.mutex);
ReleaseSemaphore(share_object.sem_stored,1,0); //通知消费
}
return 0;
}
unsigned int WINAPI consumer_thread( void* lpParameter)
{
for(int i = 0; i < NTIMES; ++i){
WaitForSingleObject(share_object.sem_stored,-1);
WaitForSingleObject(share_object.mutex,-1);
share_object.arr[i%BUFF_SIZE] = 0;
cout << "consumer modified : " << i << endl;
ReleaseMutex(share_object.mutex);
ReleaseSemaphore(share_object.sem_empty,1,0);
}
cout << "consumer done" << endl;
return 0;
}
int main(int argc, char *argv[])
{
share_object.mutex = CreateMutex(0,FALSE,0);
//注意第3个参数, 最多的数量尽量填写>=NTIMES;
// 生产者 . 初始10个
share_object.sem_empty = CreateSemaphore(NULL,10,100,NULL);
// 消费者 . 初始 0 个. 等待生产者通知 . 第三个参数别填写 最多1个.有可能消费者有问题
//具体情况参考msdn. 毕竟不像linux上的 sem_init ,可以一直涨到很大的数量
share_object.sem_stored = CreateSemaphore(NULL,0,100,NULL);
//20个生产者线程
HANDLE producer_handles[20];
for(int i = 0; i < 20; ++i)
producer_handles[i] =(HANDLE) _beginthreadex(0,0,producer_thread,0,0,0);
HANDLE consumer_handle =(HANDLE) _beginthreadex(0,0,consumer_thread,0,0,0);
WaitForMultipleObjects(5,producer_handles,TRUE,-1);
WaitForSingleObject(consumer_handle,-1);
return 0;
}
多个消费者的情况:
const int BUFF_SIZE = 10; //缓冲区大小
const int NTIMES = 50; //总共生产的个数
struct
{
HANDLE mutex;
HANDLE sem_empty; //修改成信号量, 可以用于多个线程同时访问
HANDLE sem_stored; //同上
int arr[BUFF_SIZE];
int index; //生产者处理的索引
int index_consumer; //消费者处理的索引
bool bEnd; //生产者全部处理完后,通知一下消费们,全自我了断吧.
} share_object;
unsigned int WINAPI producer_thread( void* lpParameter)
{
while(1)
{
WaitForSingleObject(share_object.sem_empty,-1) ; //等待至少一个信号量
WaitForSingleObject(share_object.mutex,-1); //多个生产者必须互斥
if(share_object.index >= NTIMES){
if(!share_object.bEnd){
share_object.bEnd = true;
//这行千万别忘了,否则消费者们将一直等待 sem_stored
ReleaseSemaphore(share_object.sem_stored,1,0);
}
ReleaseSemaphore(share_object.sem_empty,1,0);
ReleaseMutex(share_object.mutex);
break;
}
//到这里说明继续生产
share_object.arr[share_object.index++ % BUFF_SIZE] = 1;
ReleaseMutex(share_object.mutex);
ReleaseSemaphore(share_object.sem_stored,1,0); //通知消费
}
return 0;
}
unsigned int WINAPI consumer_thread( void* lpParameter)
{
while(1){
WaitForSingleObject(share_object.sem_stored,-1);
WaitForSingleObject(share_object.mutex,-1);
if(share_object.index_consumer >= NTIMES){
//到了这里说明消费者已经完成任务了
ReleaseSemaphore(share_object.sem_stored,1,0);
ReleaseMutex(share_object.mutex);
break;
}
share_object.arr[share_object.index_consumer++%BUFF_SIZE] = 0;
cout << "consumer modified : " << share_object.index_consumer << endl;
ReleaseMutex(share_object.mutex);
ReleaseSemaphore(share_object.sem_empty,1,0);
}
cout << "consumer done" << endl;
return 0;
}
int main(int argc, char *argv[])
{
share_object.mutex = CreateMutex(0,FALSE,0);
// 生产者 . 初始10个
share_object.sem_empty = CreateSemaphore(NULL,10,100,NULL);
// 消费者 . 初始 0 个. 等待生产者通知
share_object.sem_stored = CreateSemaphore(NULL,0,100,NULL);
share_object.bEnd = false;
HANDLE producer_handles[20] , consumer_handles[10];
for(int i = 0; i < 20; ++i)
producer_handles[i] =(HANDLE) _beginthreadex(0,0,producer_thread,0,0,0);
for(int i =0 ; i < 10; ++i)
consumer_handles[i] =(HANDLE) _beginthreadex(0,0,consumer_thread,0,0,0);
WaitForMultipleObjects(20,producer_handles,TRUE,-1);
WaitForMultipleObjects(10,consumer_handles,TRUE,-1);
return 0;
}