生产者和消费者
一、生产者消费者模型
在实际的开发中,经常会碰到如下场景:某个模块负责生产数据,这些数据由另一个模块来负责处理。产生数据的模块就形象的称为生产者,而处理数据的模块就称为消费者。只有生产者和消费者还不够,这个模型还必须要有一个缓冲区处于生产者和消费者之间,作为中介。生产者把数据放入缓冲区,而消费者从缓冲区中取出数据。
二、为什么要使用生产者消费者模型
1、解耦
假设生产者和消费者是两个类,如果让生产者直接调用消费者的某个函数,那么生产者和消费者之间就会产生依赖(耦合)。如果消费者的代码发生变化可能会影响到生产者。而如果两者都依赖于某个缓冲区,两者之间不直接依赖,耦合性也就降低了。
2、支持并发
生产者直接调用消费者的某个方法,还有一个弊端。由于函数调用是同步的(或者称作阻塞的),在消费者的方法没有返回之前,生产者只好一值阻塞,如果消费者处理数据很慢,则生产者就会白白浪费时间。使用生产者和消费者模式之后,生产者和消费者可以是两个独立的并发主体。生产者把制造出来的数据放到缓冲区,就可以继续生产下一个数据,而不必依赖消费者的处理速度了。
3、支持忙闲不均
缓冲区还有一个好处就是,如果制造数据的速度时快时慢,缓冲区的好处就体现出来了,当数据制造快的时候,消费者来不及处理,未处理的数据就可存放到缓冲区中。等待生产者的速度慢下来之后,消费者再慢慢处理。
三、生产者消费的关系和特点
1、生产者和消费者的模型
1.1、单个生产者和单个消费者
1.2、单个生产者和多个消费者
1.3、多个生产者和单个消费者
1.4、多个生产者和多个消费者
2、生产者和消费者之间的关系
2.1、生产者和生产者之间是互斥关系
2.2、消费者和消费者之间是互斥关系
2.3、生产者和消费者之间是同步、互斥关系
也就是:
生产者生产的时候消费者不能消费
消费者消费的时候生产者不能生产
缓冲区空时消费者不能消费
缓冲区满时生产者不能生产
例: 生产者-消费者的例子,生产者生产一个结构体串在链表的表头上,消费者从表头取一个结构体。
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<stdlib.h>
#include<assert.h>
typedef struct Node
{
int data;
struct Node * next;
}Node,*Node_p,**Node_pp;
Node_p CreatNode(int data)
{
Node_p _n=(Node_p)malloc(sizeof(Node));
if(_n==NULL)
{
return NULL;
}
_n->data=data;
_n->next=NULL;
return _n;
}
void Init(Node_pp list)
{
*list=CreatNode(0);
}
void PushFront(Node_p list ,int data)
{
assert(list);
Node_p _n=CreatNode(data);
if(_n==NULL)
{
perror("Push");
return;
}
_n->next=list->next;
list->next=_n;
}
void del_Node(Node_p del)
{
assert(del);
free(del);
}
void PopFront(Node_p list,int *data)
{
if(!isEmpty(list))
{
Node_p del=list->next;
list->next=del->next;
*data=del->data;
del_Node(del);
}
else
{
printf("list Empty\n");
}
}
int isEmpty(Node_p list)
{
assert(list);
if(list->next==NULL)
return 1;
else
return 0;
}
void destroy(Node_p list)
{
int data;
assert(list);
while(!isEmpty(list))
{
PopFront(list,&data);
}
del_Node(list);
}
void ShowList(Node_p list)
{
assert(list);
Node_p cur=list->next;
while(cur->next)
{
printf("%d->",cur->data);
cur=cur->next;
}
printf("\n");
}
Node_p list=NULL;
pthread_mutex_t mylock= PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t mycond=PTHREAD_COND_INITIALIZER;
void * Consumer(void *arg)
{
int data=0;
while(1)
{
pthread_mutex_lock(&mylock);
while(isEmpty(list))
{
pthread_cond_wait(&mycond,&mylock);
}
PopFront(list,&data);
pthread_mutex_unlock(&mylock);
printf("consumer:%d\n",data);
}
return NULL;
}
void * Producer(void *arg)
{
int data=0;
while(1)
{
usleep(123456);
data=rand()%1000;
pthread_mutex_lock(&mylock);
PushFront(list,data);
pthread_mutex_unlock(&mylock);
pthread_cond_signal(&mycond);
printf("Producer:%d\n",data);
}
return NULL;
}
int main()
{
Init(&list);
pthread_t tid1,tid2;
pthread_create(&tid1,NULL,Consumer,NULL);
pthread_create(&tid2,NULL,Producer,NULL);
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
destroy(list);
pthread_mutex_destroy(&mylock);
pthread_cond_destroy(&mycond);
return 0;
}
下一篇: 生产者和消费者