一.条件变量

    线程间的同步还有一种情况:线程A需要等某个条件成立才能继续往下执行,当条件不成立时,线程A就阻塞等待,而线程B在执行过程中使这个条件成立了,就唤醒线程A继续执行。在pthread库中通过条件变量(Condition Variable)来阻塞等待一个条件,或者唤醒等待这个条件的线程,条件变量的初始化和销毁函数如下:

    wKiom1cYtiuCO2CNAAA7sdj1owE508.png

    返回值:成功返回0,失败返回错误码。

    和Mutex的初始化和销毁类似,如果Condition Variable是静态分配的,也可以用宏定义PTHREAD_COND_INITIALIAER初始化,相当于用pthread_cond_init初始化并且参数attr为NULL。 Condition Variable的操作可以用下列函数:

    wKioL1cYuYnDaAi2AABHKNHxlmE154.png  

    返回值:成功返回0,失败返回错误号

    一个Condition Variable 总是和一个Mutex搭配使用的,一个线程可以调用pthread_cond_wait在一个Condition Variable 上阻塞等待,这个函数做已下三步:

    (1)释放Mutex

    (2)阻塞等待

    (3)当被唤醒时,重新获得Mutex并返回

    pthread_cond_timedwait函数还有一个额外的参数可以设定等待超时,如果到达了abstime所指定的时刻仍然没有别的线程来唤醒当前线程,就返回ETIMEDOUT。一个线程可以调用pthread_cond_signal唤醒在某个Condition Variable上等待的另一个线程,也可以调用pthread_cond_broadcast唤醒在这个Condition Variable上等待的所有线程。

二.演示生产者——消费者

    生产者生产一个结构体串在链表的表头上,消费者从 表头取走结构体。

    代码实现如下:

  

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<pthread.h>
  4 typedef int data_type;
  5 typedef int* data_type_p;
  6 typedef struct _node{
  7         struct _node* _next;
  8         data_type _data;
  9 }node_t,*node_p,**node_pp;
 10 node_p head=NULL;
 11 static pthread_mutex_t lock1=PTHREAD_MUTEX_INITIALIZER;
 12 static pthread_mutex_t lock2=PTHREAD_MUTEX_INITIALIZER;
 13 static pthread_mutex_t lock3=PTHREAD_MUTEX_INITIALIZER;
 14 static pthread_cond_t need_product=PTHREAD_COND_INITIALIZER;
 15 static node_p buy_node(data_type data)
 16 {
 17         node_p tmp=(node_t *)malloc(sizeof(node_t));
 18         if(tmp)
 19         {
 20                 tmp->_data=data;
 21                 tmp->_next=NULL;
 22                 return tmp;
 23         }
 24         return NULL;
 25 }
 26 void init_list(node_pp head)
 27 {
 28         *head=buy_node(0);
 29 }
 30 void push_back(node_p head,data_type data)
 31 {
 32         node_p tmp=buy_node(data);
 33         if(head->_next==NULL)
 34         {
 35                 head->_next=tmp;
 36                 tmp->_next=NULL;
 37         }
 38         else
 39         {
 40                 node_p cur=head;
 41                 while(cur->_next)
 42                 {
 43                         cur=cur->_next;
 44                 }
 45                 cur->_next=tmp;
 46                 tmp->_next=NULL;
 47         }
 48 }
 49 void push_front(node_p head,data_type data)
 50 {
 51         node_p tmp=buy_node(data);
 52         tmp->_next=head->_next;
 53         head->_next=tmp;
 54 }
 55 int pop_front(node_p head,data_type_p buf)
 56 {
 57         if(head->_next==NULL)
 58         {
 59                 *buf = -1;
 60                 return -1;
 61         }
 62         else
 63         {
 64                 node_p tmp=NULL;
 65                 tmp=head->_next;
 66                 *buf=tmp->_data;
 67                 head->_next=tmp->_next;
 68                 tmp->_next=NULL;
 69                 if(tmp)
 70                 {
 71                         free(tmp);
 72                         tmp=NULL;
 73                 }
 74                 return 0;
 75         }
 76 }
 77 void show_list(node_p head)
 78 {
 79         node_p tmp=head->_next;
 80         if(tmp)
 81         {
 82                 printf("%d ",tmp->_data);
 83                 fflush(stdout);
 84                 tmp=tmp->_next;
 85         }
 86         printf("\n");
 87 }
 88 void *product(void *arg)
 89 {
 90         pthread_mutex_lock(&lock2);
 91         int i=0;
 92         while(1)
 93         {
 94                 pthread_mutex_lock(&lock1);
 95                 printf("product success,produce num:%d,,,val is:%d\n",\
 96                         (int)arg,i);
 97                 push_back(head,i++);            //FIFO
 98                 //push_front(head,i++);        //LIFO
 99                 pthread_mutex_unlock(&lock1);
100                 pthread_cond_signal(&need_product);
101                 sleep(2);
102         }
103         pthread_mutex_unlock(&lock2);
104 }
105 void *consumer(void *arg)
106 {
107         pthread_mutex_unlock(&lock3);
108         data_type buf;
109         while(1)
110         {
111                 pthread_mutex_lock(&lock1);
112                 while(pop_front(head,&buf)==-1)
113                 {
114                         printf("wait**********\n");
115                         pthread_cond_wait(&need_product,&lock1);
116                 }
117                 pthread_mutex_unlock(&lock1);
118                 printf("consumer success,consumer num:%d,,,val is:%d\n",\
119                         (int)arg,buf);
120                 sleep(5);
121         }
122         pthread_mutex_unlock(&lock3);
123 }
124 int main()
125 {
126         init_list(&head);
127         pthread_t tid1,tid2,tid3,tid4;
128         pthread_create(&tid1,NULL,product,(void*)1);
129         pthread_create(&tid2,NULL,product,(void*)1);
130         pthread_create(&tid3,NULL,consumer,(void*)2);
131         pthread_create(&tid4,NULL,consumer,(void*)2);
132         pthread_join(tid1,NULL);
133         pthread_join(tid2,NULL);
134         pthread_join(tid3,NULL);
135         pthread_join(tid4,NULL);
136         return 0;
137 }

FIFO的运行结果:

wKioL1cY0ISgmTvkAAA9NKUK1M8366.png

 LIFO的运行结果:

wKiom1cYz-rQhTiHAAA5hThYqQM321.png

多生产者——多消费者的运行结果:

wKioL1cY0NygiSUVAABFmUKUpNw818.png