多个消费者多个生产者

版权声明: https://blog.csdn.net/dashoumeixi/article/details/83415800

之前的是单生产消费者 使用一个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;
}

猜你喜欢

转载自blog.csdn.net/dashoumeixi/article/details/83415800
今日推荐