线程同步之条件变量

简介:

一.概述:

    条件变量是线程同步的一种机制,它是通过一个条件,当条件满足时,唤醒一个线程,但条件不满足时,挂起该线程。由于同步是伴随着互斥的,所以条件变量一般都伴随着互斥锁。




二.相关函数:

(1).cond:pthread_cond_t  cond  =  PTHREAD_COND_INITIALIZER

     cond是一个全局变量,和mutex一样。

(2).pthread_cond_init函数:int  pthread_cond_init(pthread_cond_t  *restrict  cond, 

                                                                                   const  pthread_condattr_t  *restrict  attr)

attr参数:用于初始化cond,NULL表示缺省属性。weiNULL时和声明一个全局的cond一样。

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

PS:restrict,C语言中的一种类型限定符(TypeQualifiers),用于告诉编译器,对象已经被指针所引用,不能通过除该指针外所有其他直接或间接的方式修改该对象的内容。

(3).phtread_cond_destroy函数:int  pthread_cond_destroy(pthread_cond_t *cond)

函数功能:销毁cond。

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

(4).pthread_cond_timedwait函数:int  pthread_cond_timedwait(pthread_cond_t *restrict  cond, 

                                                                                                     pthread_mutex_t *restrict  mutex,

                                                                                                     const  struct timespaec *restrict abstime)

函数功能:将当前线程挂起,直到有信号将其唤醒或出现错误返回。

sbstime参数:等待超时时间,如果到达了abstime所指定的 时刻仍然没有别的线程来唤醒当前线程,就返回ETIMEDOUT。

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

(5).pthread_cond_wait函数:int  pthread_cond_timedwait(pthread_cond_t *restrict  cond, 

                                                                                                     pthread_mutex_t *restrict  mutex)

函数功能:将当前线程挂起,直到有信号将其唤醒或出现错误返回。

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

(6).pthread_cond_signal函数:int pthread_cond_signal(pthread_cond_t *cond)

函数功能:发出一个信号给用cond等待挂起的线程,使之进入就绪态。

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

(7).pthread_cond_broadcastsignal函数:int pthread_cond_signal(pthread_cond_t *cond)

函数功能:发出一个信号给所有用cond等待挂起的线程,使它们都进入就绪态。

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




三.相关代码:(生产者与消费者模型)(必须是生产者先生产,消费者再消费的顺序)

在没有加互斥锁和条件变量之前:

1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<malloc.h>
  4 #include<pthread.h>
  5 
  6 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
  7 static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
  8 
  9 typedef struct node
 10 {
 11     int _data;
 12     struct node* _next;
 13 }node_t, *node_p, **node_pp;
 14 
 15 node_p head = NULL;
 16 int g_data;                   //用于表示消费的数据
 17 
 18 node_p buy_node(int data)                                                                                                                                      
 19 {
 20     node_p tem = malloc(sizeof(node_t));
 21     if(tem)
 22     {   
 23         tem->_data = data;
 24         tem->_next = NULL;
 25         return tem;
 26     }
 27     return NULL;
 28 }
 29 
 30 
 31 void init_list(node_pp list)
 32 {
 33     *list = buy_node(0);
 34 }
 35 
 36 void head_push(node_p list, int data)
 37 {
 38     node_p tem = buy_node(data);
 39     tem->_next = list->_next;
 40     list->_next = tem;
 41 }
 42 
 43 int tail_pop(node_p list)
 44 {
 45     if(list->_next == NULL)
 46     {
 47         g_data = -1;
 48         return -1;
 49     }
 50 
 51     node_p tem = list;
 52     node_p del = NULL;
 53     while(tem->_next != NULL)
 54     {
 55         del = tem->_next;
 56         if(tem->_next->_next == NULL)
 57         {                                                                                                                                                      
 58             tem->_next = NULL;
 59         }
 60         else
 61         {   
 62             tem = tem->_next;
 63         }
 64     }
 65     
 66     g_data = del->_data;
 67     free(del);
 68     return 0;
 69 }
 70 
 71 void show_list(node_p list)
 72 {
 73     node_p tem = list;
 74     while(tem != NULL)
 75     {
 76         printf("%d  ",tem->_data);
 77         tem = tem->_next;
 78     }
 79     printf("\n");
 80 }
 81 
 82 void* product(void* ptr)
 83 {
 84     int i = 1;
 85     while(1)
 86     {
 87         head_push(head, i);
 88         sleep(1);
 89         printf("product data -> %d\n",i);
 90         i++;
 91     }
 92 }
 93 
 94 void* consumer(void* ptr)
 95 {
 96     while(1)
 97     {
 98         tail_pop(head);
 99         sleep(1);
100         printf("consumer data -> %d\n", g_data);
101     }
102 }
103 
104 
105 
106 
107 int main()
108 {
109     init_list(&head);
110 
111                                                                                                                                                                
112     pthread_t tid1, tid2;
113     pthread_create(&tid1, NULL, product, NULL);
114     pthread_create(&tid2,NULL, consumer, NULL);
115     pthread_join(tid1, NULL);
116     pthread_join(tid2, NULL);
117 
118     pthread_mutex_destroy(&lock);
119     pthread_cond_destroy(&cond);
120 
121 
122 //  int i = 1;
123 //  while(i <= 5)
124 //  {
125 //      head_push(head, i++);
126 //      show_list(head);
127 //  }
128 //  printf("-------------------------------------\n");
129 //  while(i >= 1)
130 //  {
131 //      tail_pop(head);
132 //      show_list(head);
133 //      i--;
134 //  }
135 
136     return 0;
137 }
138 
139 
140

执行结果:

wKioL1cZj16jCOs4AAA6xMMOTTA229.png

PS:可以看到结果为消费者先消费,而不是生产者先生产。



用互斥锁和条件变量:

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<malloc.h>
  4 #include<pthread.h>
  5 
  6 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
  7 static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
  8 
  9 typedef struct node
 10 {
 11     int _data;
 12     struct node* _next;
 13 }node_t, *node_p, **node_pp;
 14 
 15 node_p head = NULL;            //头指针
 16 int g_data;                   //用于表示消费的数据
 17 
 18 node_p buy_node(int data)
 19 {
 20     node_p tem = malloc(sizeof(node_t));
 21    
 
if(tem)                                                                                                                                                  
  
 22     {   
 23         tem->_data = data;
 24         tem->_next = NULL;
 25         return tem;
 26     }
 27     return NULL;
 28 }
 29 
 30 
 31 void init_list(node_pp list)
 32 {
 33     *list = buy_node(0);
 34 }
 35 
 36 void head_push(node_p list, int data)
 37 {
 38     node_p tem = buy_node(data);
 39     tem->_next = list->_next;
 40     list->_next = tem;
 41 }
 42 
 43 int tail_pop(node_p list)
 44 {
 45     if(list->_next == NULL)

 46     
{                                                                                                                                                        
  
 47         g_data = -1;
 48         return -1;
 49     }
 50     
 51     node_p tem = list;
 52     node_p del = NULL;
 53     while(tem->_next != NULL)
 54     {   
 55         del = tem->_next;
 56         if(tem->_next->_next == NULL)
 57         {   
 58             tem->_next = NULL;
 59         }
 60         else
 61         {   
 62             tem = tem->_next;
 63         }
 64     }
 65     
 66     g_data = del->_data;
 67     free(del);
 68     return 0;
 69 }
 70 
 71 void show_list(node_p list)
 72 {
 73     node_p tem = list;
 74     while(tem != NULL)
 75     {
 76         printf("%d  ",tem->_data);
 77         tem = tem->_next;
 78     }
 79     printf("\n");
 80 }
 81 
 82 void* product(void* ptr)
 83 {
 84     int i = 1;
 85     while(1)
 86     {
 87         pthread_mutex_lock(&lock);
 88         head_push(head, i);
 89         sleep(1);
 90         i++;
 91         pthread_mutex_unlock(&lock);
 92         printf("product data -> %d\n",i);
 93         pthread_cond_signal(&cond);     //生产一个就可以唤醒消费者了
 94     }
 95 }
 96 
 97 void* consumer(void* ptr)
 98 {
 99     while(1)
100     {
101         pthread_mutex_lock(&lock);
102         while(head->_next == NULL)      //注意要用while为不是if  因为可能会出现一个错误信号把
103         {                               //该线程唤醒,但链表内并没有数据的可能。 
104             pthread_cond_wait(&cond, &lock);
105         }
106         tail_pop(head);
107         sleep(1);
108         pthread_mutex_unlock(&lock);
109         printf("consumer data -> %d\n", g_data);
110     }
111 }
112 
113 
114 int main()
115 {
116     init_list(&head);
117 
118 
119     pthread_t tid1, tid2;
120     pthread_create(&tid1, NULL, product, NULL);
121     pthread_create(&tid2,NULL, consumer, NULL);
122     pthread_join(tid1, NULL);
123     pthread_join(tid2, NULL);
124 
125     pthread_mutex_destroy(&lock);
126     pthread_cond_destroy(&cond);
127 
128 
129//  int i = 1;                                                                                                                                               
130 //  while(i <= 5)
131 //  {
132 //      head_push(head, i++);
133 //      show_list(head);
134 //  }
135 //  printf("-------------------------------------\n");
136 //  while(i >= 1)
137 //  {
138 //      tail_pop(head);
139 //      show_list(head);
140 //      i--;
141 //  }
142 
143     return 0;
144 }
145 
146 
147                                                                                                                                                              
  
                                                                                                                                                
 147,0-1      底端

                                                                                                                                               
 129,1         82%

执行结果:

wKioL1cZlmfBE3JRAAA-bC2IiMk963.png










本文转自 ye小灰灰  51CTO博客,原文链接:http://blog.51cto.com/10704527/1766621,如需转载请自行联系原作者
目录
相关文章
|
1月前
|
存储 Java 测试技术
ThreadLocal:线程专属的变量
ThreadLocal:线程专属的变量
41 0
|
7月前
|
Java 调度
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(3)
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(3)
|
7月前
|
Java 应用服务中间件 容器
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(4)
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(4)
|
7月前
|
Java 应用服务中间件
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(5)
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(5)
|
7月前
|
Java 物联网 应用服务中间件
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(6)
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(6)
|
7月前
|
缓存 算法 Java
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(7)
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(7)
|
7月前
|
Java 数据库连接
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(9)
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(9)
|
7月前
|
Java
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(10)
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(10)
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(10)
|
7月前
|
Java
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(11)
带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(11)
|
6月前
|
程序员 调度
多线程的创建,复习匿名内部类,Thread的一些方法,以及lambda的变量捕捉,join用法(二)
多线程的创建,复习匿名内部类,Thread的一些方法,以及lambda的变量捕捉,join用法

热门文章

最新文章