生产者消费者模型在操作系统中,是很常见的模型之一。它们之间的关系,生产者负责生产产品,消费者负责消费产品。
“产品”是它们的关联属性。 依照我们的操作系统理念。这个产品就是共享区。
我们把这块共享区设置成队列,内存块,都是可以的,我们把该共享区称为“仓库”。
看一下模型:
生产者消费者模型中,最重要的性质:
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;
}
运行结果如图:
生产者与生产者之间,是互斥的关系,因为当生产出一个产品的时候,如果其他生产者也生产出了产品,两个线程同时挂载到链表中,这就发生了冲突。 消费者也是如此,如果两个消费者同时消费仓库中的产品,会导致一个产品多个消费者去消费,产生问题。 生产者与消费者之间,目的都是为了消费者消费产品,(为了完成某个任务,同步进行)所以存在着同步的关系。
简单的生产者消费者模型就这样,不过上面的例子使用的仓库是 链表 的形式,而在操作系统中,仓库可以是很多种,队列,共享内存等,都可以成为仓库。有兴趣的可以把队列换成其他。