一、相关概念:
同步和互斥是进程间很重要的交互模式,而生产者和消费者问题则是同步和互斥的一个经典模型。
同步是一种时序关系。如规定了进程1 处理完事情A后,进程2 才能处理事情 B,经典的同步问题是生产者和消费者间的同步。
互斥描述的是一种独占关系。如任一时刻,进城1 和进程2 中只能有一个写文件C。
生产者-消费者问题:
1、在同一个进程地址空间内执行的两个线程生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。消费者线程从缓冲区中获得物品,然后释放缓冲区。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。
2、生产者中先同步再互斥,而消费者先互斥再同步,或反之;以及生产者和消费者都先互斥再同步这几种情况都不会死锁,因为它们间并没有交叉关系,就更不可能形成死锁环。之所以先同步,再互斥,是为了更好的并发性:并发性的瓶颈是互斥区,先同步再互斥,使得互斥区代码更短。
二、单 生产者-消费者模型:
输入时,输入线程(插入等)是生产者,而计算线程是消费者;
输出时,计算线程(删除等)是生产者,而打印线程是消费者。
//链表:头进 尾出
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
typedef int data_type;
typedef int* data_type_p;
typedef struct _node
{
data_type data;
struct _node *next;
}node_t,*node_p,**node_pp;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
node_p head=NULL;
static node_p buy_node(data_type _data)
{
node_p tmp=malloc(sizeof(node_p));
if(tmp)
{
tmp->data=_data;
tmp->next=NULL;
return tmp;
}
return NULL;
}
void init_list(node_pp _phead)
{
*_phead=buy_node(0);
}
void delete_node(node_p tmp)
{
if(tmp)
{
free(tmp);
tmp=NULL;
}
}
int pop_node(node_p list,data_type_p _data_p)
{
if(list->next == NULL)
{
*_data_p=-1;
return -1;
}
node_p tmp=list->next;
list->next=tmp->next;
*_data_p=tmp->data;
delete_node(tmp);
return 0;
}
void push_node(node_p list,data_type _data)
{
node_p tmp=buy_node(_data);
tmp->next=list;
list->next=tmp;
}
void show_list(node_p list)
{
node_p cur=list;
while(cur)
{
printf("%d ",cur->data);
fflush(stdout);
cur=cur->next;
}
}
void *product(void *arg)
{
int i=0;
while(1)
{
pthread_mutex_lock(&lock);
printf("product data:%d\n",i++);
push_node(head,i++);
printf("product done ... wakeup consumer\n");
pthread_mutex_unlock(&lock);
pthread_cond_signal(&cond);
sleep(1);
}
}
void *consumer(void *arg)
{
data_type _data;
while(1)
{
pthread_mutex_lock(&lock);
while(-1 == pop_node(head,&_data));
{
pthread_cond_wait(&cond,&lock);
}
printf("consumer data:%d\n",_data);
pthread_mutex_unlock(&lock);
sleep(1);
}
}
int main()
{
pthread_cond_t cond;
pthread_cond_init(&cond,NULL);
pthread_t tid1,tid2;
pthread_create(&tid1,NULL,product,NULL);
pthread_create(&tid2,NULL,consumer,NULL);
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
pthread_cond_destroy(&cond);
return 0;
}//链表的更改:尾进 头出
... ...
int pop_node(node_p list,data_type_p _data_p)
{
if(list->next == NULL)
{
*_data_p=-1;
return -1;
}
node_p tmp=list;
list=list->next;
delete_node(tmp);
return 0;
}
void push_node(node_p list,data_type _data)
{
node_p tmp=buy_node(_data);
while(list->next)
{
list=list->next;
}
list->next=tmp;
tmp->data=_data;
tmp->next=NULL;
}
... ...三、多生产者-消费者模型:
// 其余代码见上
int main()
{
pthread_cond_t cond;
pthread_cond_init(&cond,NULL);
pthread_t tid1,tid2,tid3,tid4;
pthread_create(&tid1,NULL,product,NULL);
pthread_create(&tid2,NULL,product,NULL);
pthread_create(&tid3,NULL,consumer,NULL);
pthread_create(&tid4,NULL,consumer,NULL);
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
pthread_join(tid3,NULL);
pthread_join(tid4,NULL);
pthread_cond_destroy(&cond);
return 0;
}注意 :生产者消费者问题,是同步和互斥的一个经典模型。但需要注意死锁问题,需要先同步再互斥。
本文出自 “花开彼岸” 博客,请务必保留此出处http://zxtong.blog.51cto.com/10697148/1766832
原文:http://zxtong.blog.51cto.com/10697148/1766832