条件变量
有关函数:
当向条件变量发送一个信号时,如果没有线程等待在条件变量,那么该信号会丢失。
生产者消费者模型:
关系:
同步
生产者<—————>消费者
互斥
互斥
生产者<—————>生产者
互斥
消费者<—————>消费者
场所:
缓冲区,下文以链表方式实现
1.单个生产者,单个消费者,且生产者和消费者访问链表的顺序是LIFO的
代码实现:
#include<stdio.h>
#include<pthread.h>
pthread_mutex_t _mutex_lock=PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t need_product=PTHREAD_COND_INITIALIZER;
typedef struct List List;
struct List
{
int _var;
List *_next;
}*head=NULL;
//head=NULL;
void* product(void *arg)
{
while(1){
pthread_mutex_lock(&_mutex_lock);
List* p=(List*)malloc(sizeof(List));
p->_var=(rand()%2000);
p->_next=head;
head=p;
printf("call consumer! product success,val is :%d\n",p->_var);
pthread_mutex_unlock(&_mutex_lock);
sleep(rand()%3);
pthread_cond_signal(&need_product);
}
}
void* consumer(void *arg)
{
while(1){
pthread_mutex_lock(&_mutex_lock);
if(head==NULL){
pthread_cond_wait(&need_product,&_mutex_lock);
}
List *p=head;
head=head->_next;
p->_next=NULL;
pthread_mutex_unlock(&_mutex_lock);
printf("consumer has get protect:%d\n",p->_var);
free((void*)p);
p=NULL;
}
}
int main()
{
int err;
pthread_t p;
pthread_t c;
err=pthread_create(&p,NULL,product,NULL);
if(err!=0){
printf("%s\n",strerror(err));
}
err=pthread_create(&c,NULL,consumer,NULL);
if(err!=0){
printf("%s\n",strerror(err));
}
void *status;
pthread_join(p,&status);
printf("%s\n",status);
pthread_join(c,&status);
printf("%s\n",status);
pthread_cond_destroy(&need_product);
pthread_mutex_destroy(&_mutex_lock);
return 0;
}
运行结果:
==================================================================
2.单个生产者,单个消费者,且生产者和消费者访问链表的顺序是FIFO的
代码实现:
fifo_cond.c
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
//pthread_cond_t need_product=PTHREAD_COND_INITIALIZER;
pthread_cond_t need_product;
typedef int datatype;
typedef struct node{
datatype _val;
struct node *_next;
}node,*node_p,**node_pp;
typedef struct list_info
{
node_p _head;
node_p _tail;
}list_info,*list_info_p;
void init_list(node_pp head,node_pp last)
{
*head=NULL;
*last=*head;
}
node_p buy_node(datatype data)
{
node_p p=(node_p)malloc(sizeof(node));
p->_val=data;
p->_next=NULL;
if(p==NULL){
return NULL;
}
return p;
}
int push(node_pp list,node_pp last,datatype data)
{
node_p p=buy_node(data);
if(p==NULL){
return -1;
}
if(*last==NULL){
*last=p;
*list=p;
}
else{
(*last)->_next=p;
(*last)=(*last)->_next;
}
return data;
}
node_p destroy_node(node_pp list,node_pp last)
{
if((*list)!=NULL){
node_p tmp=*list;
*list=(*list)->_next;
return tmp;
}
*last=NULL;
return NULL;
}
int pop(node_pp list,node_pp last)
{
node_p p=destroy_node(list,last);
if(p==NULL)
return -1;
int data=p->_val;
free(p);
p=NULL;
return data;
}
int show_list(node_p list,node_p last)
{
while(list!=last){
printf("%d->",list->_val);
list=list->_next;
}
if(last!=NULL)
printf("%d\n",last->_val);
}
void *product(void *arg)
{
while(1){
datatype data=rand()%100;
pthread_mutex_lock(&lock);
push(&(((list_info_p)arg)->_head),&(((list_info_p)arg)->_tail),data);
printf("Product success,val:%d\n",data);
pthread_mutex_unlock(&lock);
sleep(2);
pthread_cond_signal(&need_product);
}
}
void *consumer(void *arg)
{
while(1){
int ret=-1;
// sleep(4);
pthread_mutex_lock(&lock);
while(-1==(ret=pop(&(((list_info_p)arg)->_head),&(((list_info_p)arg)->_tail)))){
pthread_cond_wait(&need_product,&lock);
}
pthread_mutex_unlock(&lock);
printf("consumer success,val:%d\n",ret);
}
}
int main()
{
pthread_cond_init(&need_product,NULL);
node_p head,tail;
init_list(&head,&tail);
list_info _list_info;
_list_info._head=head;
_list_info._tail=tail;
pthread_t tid1,tid2;
pthread_create(&tid1,NULL,product,(void*)(&_list_info));
pthread_create(&tid2,NULL,consumer,(void*)(&_list_info));
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
pthread_cond_destroy(&need_product);
pthread_mutex_destroy(&lock);
// int data=0;
// while(data<10){
// push(&head,&last,data);
// show_list(head,last);
// data++;
// }
//
// while(data>0){
// pop(&head,&last);
// show_list(head,last);
// data--;
// }
return 0;
}
运行结果:
consumer()有sleep(4);
运行结果:
consumer()函数中没有sleep(4)这条语句
从以上两次结果可以看出消费者是按找生产产品的顺序来消费的,如果生产者生产的慢,消费者会等待
==================================================================
3.多个生产者,多个消费者
实现代码:
include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
//pthread_cond_t need_product=PTHREAD_COND_INITIALIZER;
pthread_cond_t need_product;
typedef int datatype;
typedef struct node{
datatype _val;
struct node *_next;
}node,*node_p,**node_pp;
node_p head,tail;
typedef struct list_info
{
node_p _head;
node_p _tail;
int _flag;
}list_info,*list_info_p;
void init_list(node_pp head,node_pp last)
{
*head=NULL;
*last=*head;
}
node_p buy_node(datatype data)
{
node_p p=(node_p)malloc(sizeof(node));
p->_val=data;
p->_next=NULL;
if(p==NULL){
return NULL;
}
return p;
}
int push(node_pp list,node_pp last,datatype data)
{
node_p p=buy_node(data);
if(p==NULL){
return -1;
}
if(*last==NULL){
*last=p;
*list=p;
}
else{
(*last)->_next=p;
(*last)=(*last)->_next;
}
return data;
}
node_p destroy_node(node_pp list,node_pp last)
{
if((*list)!=NULL){
node_p tmp=*list;
*list=(*list)->_next;
// if(*list==NULL) //###########error###############
// *last==NULL;
return tmp;
}
*last=NULL;
return NULL;
}
int pop(node_pp list,node_pp last)
{
node_p p=destroy_node(list,last);
if(p==NULL)
return -1;
int data=p->_val;
free(p);
p=NULL;
return data;
}
int show_list(node_p list,node_p last)
{
while(list!=last){
printf("%d->",list->_val);
list=list->_next;
}
if(last!=NULL)
printf("%d\n",last->_val);
}
void *product(void *arg)
{
while(1){
datatype data=rand()%100;
pthread_mutex_lock(&lock);
push(&head,&tail,data);
printf("Product%d put success,val:%d\n",(int)arg,data);
pthread_mutex_unlock(&lock);
sleep(1);
// pthread_cond_signal(&need_product);
pthread_cond_broadcast(&need_product);
}
}
void *consumer(void *arg)
{
while(1){
int ret=-1;
sleep(2);
pthread_mutex_lock(&lock);
while(-1==(ret=pop(&head,&tail))){
pthread_cond_wait(&need_product,&lock);
}
pthread_mutex_unlock(&lock);
sleep(1);
printf("consumer%d take success,val:%d\n",(int)arg,ret);
}
}
int main()
{
init_list(&head,&tail);
pthread_t tid1,tid2;
pthread_create(&tid1,NULL,product,(void*)1);
pthread_create(&tid2,NULL,product,(void*)2);
pthread_t tid3,tid4,tid5;
pthread_create(&tid3,NULL,consumer,(void*)3);
pthread_create(&tid4,NULL,consumer,(void*)4);
pthread_create(&tid5,NULL,consumer,(void*)5);
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
pthread_join(tid3,NULL);
pthread_join(tid4,NULL);
pthread_join(tid5,NULL);
pthread_cond_destroy(&need_product);
pthread_mutex_destroy(&lock);
return 0;
}
运行结果:
以上有2个生产者,3个消费者 生产者生产出的数据放入同一链表中,消费者也都从该链表取数据,任何一刻对象对改链表进行操作时,别的对象都不能对该链表进行操作,实现了互斥功能。