操作系统——生产者消费者模型

生产者消费者模型在操作系统中,是很常见的模型之一。它们之间的关系,生产者负责生产产品,消费者负责消费产品。
“产品”是它们的关联属性。 依照我们的操作系统理念。这个产品就是共享区。
我们把这块共享区设置成队列,内存块,都是可以的,我们把该共享区称为“仓库”。

看一下模型:
这里写图片描述

生产者消费者模型中,最重要的性质:
1.生产者与消费者是同步的关系
2.生产者与生产者之间是互斥的关系
3.消费者与消费者之间是互斥的关系

如下代码,具体函数我已经注释,仔细看下,就会懂整个生产消费的过程:

/*************************************************************************
        > File Name: pro_con.c
        > Author: 
        > Mail: 
        > Created Time: Wed 01 Aug 2018 10:41:22 PM PDT
 ************************************************************************/

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<malloc.h>
#include<string.h>
#include<pthread.h>

#define CONSUMERS_COUNT 3 
#define PRODUCERS_COUNT 3

//仓库中的产品(队列)
struct msg
{
    struct msg *next;
    int num;
};

struct msg *head = NULL;

pthread_cond_t cond;
pthread_mutex_t mutex;
pthread_t thread[CONSUMERS_COUNT + PRODUCERS_COUNT];


//消费者线程的线程函数 
void *consumer(void* p)
{
    int num = *(int *)p;
    free(p);
    struct msg *mp;

    while(1)
    {
        //消费者与消费者之间 互斥,上锁
        pthread_mutex_lock(&mutex);
        while(head == NULL)
        {
            printf("%d begin wait a condtion...\n",num);

            //仓库为空,消费者阻塞,直到收到生产者发出生产完成信号
            pthread_cond_wait(&cond,&mutex);
        }

        printf("%d end wait a condtion..\n",num);
        printf("%d begin consume product..\n",num);

        mp = head;
        head = mp->next;
        //消费者消费完了,解锁
        pthread_mutex_unlock(&mutex);
        printf("consume %d\n",mp->num);

        free(mp);
        printf("%d end consume product..\n",num);
        sleep(rand()%5);
    }
}

//生产者线程函数
void *produce(void *p)
{
    struct msg *mp;
    int num = *(int *)p;
    free(p);

    while(1)
    {
        printf("%d begin produce product..\n",num);
        mp = (struct msg*)malloc(sizeof(struct msg));
        mp->num = rand()%1000+1;
        printf("produce %d\n",mp->num);
        //生产者与生产者之间互斥
        pthread_mutex_lock(&mutex);

        mp->next = head;
        head = mp;

        printf("%d end produce product..\n");
        //生产完成,发出信号,使消费者线程开始消费
        pthread_cond_signal(&cond);
        //解锁
        pthread_mutex_unlock(&mutex);
        sleep(rand()%5);
    }
}


int main()
{

    srand(time(NULL));
    pthread_cond_init(&cond,NULL);
    pthread_mutex_init(&mutex,NULL);

    //消费者线程3个
    int i;
    for(i = 0;i < CONSUMERS_COUNT;i ++)
    {
        int *p = (int *)malloc(sizeof(int));
        *p = i;
        pthread_create(&thread[i],NULL,consumer,(void *)p);

    }

    //生产者线程3个
    for(i = 0;i < PRODUCERS_COUNT;i ++)
    {
        int *p = (int *)malloc(sizeof(int));
        *p = i;
        pthread_create(&thread[CONSUMERS_COUNT + i], NULL , produce ,(void *)p);

    }

    //线程等待
    for(i = 0;i < CONSUMERS_COUNT + PRODUCERS_COUNT;i++)
    {
        pthread_join(thread[i],NULL);
    }


    //消费条件变量,互斥量
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);


    return 0;
}

运行结果如图:
这里写图片描述

生产者与生产者之间,是互斥的关系,因为当生产出一个产品的时候,如果其他生产者也生产出了产品,两个线程同时挂载到链表中,这就发生了冲突。 消费者也是如此,如果两个消费者同时消费仓库中的产品,会导致一个产品多个消费者去消费,产生问题。 生产者与消费者之间,目的都是为了消费者消费产品,(为了完成某个任务,同步进行)所以存在着同步的关系。

简单的生产者消费者模型就这样,不过上面的例子使用的仓库是 链表 的形式,而在操作系统中,仓库可以是很多种,队列,共享内存等,都可以成为仓库。有兴趣的可以把队列换成其他。

猜你喜欢

转载自blog.csdn.net/Shawei_/article/details/81382935