生产者/消费者问题。可以从下图中看到,有一个容器用来存放数据,我们可以把这个容器当作”交易场所“或者”仓库“,生产者只关心仓库是否存满,不需要关心消费者的情况。消费者也一样,不需要关心具体生产者的情况,具体有多少个生产者,只需要知道仓库中是否有数据,双方甚至都不知道对方的存在。
生产者消费者,是在多线程同步的一个问题,两个固定大小缓冲区的线程,在实际运行是会发生问题,生产者是生成数据放入缓冲区,重复过程,消费者在缓冲区取走数据。
总结下来就是“三、二、一原则”:
三种关系:
- 生产者之间的竞争关系
- 消费者之间的竞争关系
- 生产者和消费者之间的关系
两个角色:生产者和消费者
一个场所:有效的内存区域
比如现在可以把生产者/消费者想象成供货商以及顾客的关系。仓库就是超市。
现在我们用单链表来模拟顾客/供货商/超市。然后运用上一篇刚刚学到的互斥量和条件变量来解决这个问题。
- 基于单链表的生产者互斥者模型
代码:
/*************************************************************************
> File Name: mycp.c
> Author:
> Mail:
> Created Time: Sun 18 Jun 2017 04:55:37 AM PDT
************************************************************************/
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<stdlib.h>
typedef struct _node{
int data;
struct _node* next;
}node_t,*node_p,**node_pp;
node_p head=NULL;
pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
static node_p alloc_node(int data)
{
node_p tmp=(node_p)malloc(sizeof(node_t));
if(tmp==NULL)
{
perror("malloc");
exit(1);
}
tmp->data=data;
tmp->next=NULL;
return tmp;
}
static void delete_node(node_p n)
{
if(n!=NULL)
free(n);
}
static int isEmpty(node_p h)
{
return h->next==NULL;
}
void initList(node_pp h)
{
*h=alloc_node(0);
}
void pushFront(node_p h,int data)
{
node_p tmp=alloc_node(data);
tmp->next=h->next;
h->next=tmp;
}
void popFront(node_p h,int* out)
{
if(!isEmpty(h))
{
node_p p=h->next;
h->next=p->next;
*out = p->data;
delete_node(p);
}
}
void destoryList(node_p h)
{
int out=0;
while(!isEmpty(h))
{
popFront(h,&out);
}
delete_node(h);
}
void showList(node_p h)
{
node_p start=h->next;
while(start)
{
printf("%d ",start->data);
start=start->next;
}
printf("\n");
}
void *product(void *arg)//生产
{
while(1)
{
int data=rand()%1234;
pthread_mutex_lock(&lock);
pushFront(head,data);
pthread_mutex_unlock(&lock);
pthread_cond_signal(&cond);
printf("product done: %d",data);
sleep(1);
}
}
void *consume(void *arg)//消费
{
int c=-1;
while(1)
{
pthread_mutex_lock(&lock);
while(isEmpty(head))
{
printf("consume begin waiting...\n");
pthread_cond_wait(&cond,&lock);
}
popFront(head,&c);
printf("consumer done: %d\n",c);
pthread_mutex_unlock(&lock);
}
}
int main()
{
initList(&head);
pthread_t p,c;
pthread_create(&p,NULL,product,NULL);
pthread_create(&c,NULL,consume,NULL);
pthread_join(p,NULL);
pthread_join(c,NULL);
pthread_mutex_destroy(&lock);
pthread_cond_destroy(&cond);
destoryList(head);
return 0;
}
生产者生产节点,消费者消费节点,如果现在链表中没有节点则等待。