我是靠谱客的博主 淡淡星星,最近开发中收集的这篇文章主要介绍浅析linux下的条件变量,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

  一.条件变量

    条件变量是用来等待线程而不是上锁的,条件变量通常和互斥锁一起使用。条件变量之所以要和互斥锁一起使用,主要是因为互斥锁的一个明显的特点就是它只有两种状态:锁定和非锁定,而条件变量可以通过允许线程阻塞和等待另一个线程发送信号来弥补互斥锁的不足,所以互斥锁和条件变量通常一起使用

    当条件满足的时候,线程通常解锁并等待该条件发生变化,一旦另一个线程修改了环境变量,就会通知相应的环境变量唤醒一个或者多个被这个条件变量阻塞的线程。这些被唤醒的线程将重新上锁,并测试条件是否满足。一般来说条件变量被用于线程间的同步;当条件不满足的时候,允许其中的一个执行流挂起和等待。

条件变量中常用的API:

     1).条件变量类型为:pthread_cond_t ,类似互斥变量,条件变量的初始化有两种方式:

      静态:pthread_cond_t mycon=PTHREAD_COND_INITIALIZER;

      动态:通过调用pthread_cond_init函数,函数原型为:

[cpp]  view plain  copy
  1. 静态:pthread_cond_t mycon=PTHREAD_COND_INITIALIZER;  

     cond:环境变量.

     attr:条件变量属性.

     成功返回0,失败返回错误码.

     2).条件变量摧毁函数:pthread_cond_destroy(&mycond);

[cpp]  view plain  copy
  1. int pthread_cond_destroy(pthread_cond_t *cond);  

     成功返回0,失败返回错误码.

     摧毁所指定的条件变量,同时将会释放所给它分配的资源。调用该函数的进程也并不等待在参数所指定的条件变量上。

     3).条件变量等待函数。pthread_cond_wait(&mycond,&mylock);

     

[cpp]  view plain  copy
  1. int pthread_cond_timedwait(pthread_cond_t *restrict cond,  
  2.            pthread_mutex_t *restrict mutex,  
  3.            const struct timespec *restrict abstime);  
  4.     int pthread_cond_wait(pthread_cond_t *restrict cond,  
  5.            pthread_mutex_t *restrict mutex);  

    cond:条件变量

    mutex:互斥锁

 pthread_cond_wait和pthread_cond_timedwait的区别:

    pthread_cond_timedwait函数类型与函数pthread_cond_wait,区别在于,如果达到或是超过所引用的参数*abstime,它将结束并返回错误ETIME.

    timespec

[cpp]  view plain  copy
  1. typedef struct timespec  
  2.    {  
  3.       time_t     tv_sec;    //!> 秒  
  4.       long     tv_nsex;    //!> 毫秒  
  5.    }timespec_t;  

    当时间超过之前预设定的时会返回错误.

    4).条件变量通知函数:pthread_cond_signal和pthread_cond_broadcast

[cpp]  view plain  copy
  1. int pthread_cond_broadcast(pthread_cond_t *cond);  
  2. int pthread_cond_signal(pthread_cond_t *cond);  

pthread_cond_signal和pthread_cond_broadcast的区别:

       pthread_cond_signal:只唤醒一个在相同条件变量中阻塞的线程将会被唤醒

       pthread_cond_broadcast:唤醒等待队列中的所有线程

二.一个关于互斥锁和条件变量的栗子

   栗子:用互斥锁和条件变量的概念实现一个简单的生产者和消费者的模型。

 生产者和消费者模型:

    1).满足互斥与同步条件,用互斥锁和条件变量实现

    2).多个生产者和消费者:生产者和生产者属于互斥关系;生产者和消费者属于互斥和同步关系;消费者和消费者属于竞争关系,需要互斥锁

    3).生产者和消费者模型中存在如下几种关系和角色:3种关系,2种角色,1种交换媒介(一般是一段内存)

    下例以单生产者和单消费者,交换媒介为链表实现的生产者消费者模型

     

[cpp]  view plain  copy
  1. procon.c  
  2.   
  3. #include<stdio.h>  
  4. #include<stdlib.h>  
  5. #include<assert.h>  
  6. #include<pthread.h>  
  7.   
  8. typedef struct LinkNode  
  9. {  
  10.     int data;  
  11.     struct LinkNode *next;  
  12. }Node;  
  13.   
  14. pthread_mutex_t mylock=PTHREAD_MUTEX_INITIALIZER;  
  15. pthread_cond_t mycond=PTHREAD_COND_INITIALIZER;  
  16.   
  17. Node *CreatNode(int data)  
  18. {  
  19.     Node *NewNode=(Node *)malloc(sizeof(Node));  
  20.     if(NULL == NewNode)  
  21.     {  
  22.         perror("malloc");  
  23.         return NULL;  
  24.     }  
  25.     NewNode->data=data;  
  26.     NewNode->next=NULL;  
  27.     return NewNode;  
  28. }  
  29.   
  30. void InitLink(Node **head)  
  31. {  
  32.     *head=CreatNode(0);  
  33. }  
  34.   
  35. int IsEmpty(Node *head)  
  36. {  
  37.     assert(head);  
  38.     if(head->next)  
  39.         return 0;    //not empty  
  40.     else  
  41.         return 1;    //empty  
  42. }  
  43.   
  44. void PushFront(Node *head,int data)  
  45. {  
  46.     assert(head);  
  47.     Node *NewNode=CreatNode(data);  
  48.     NewNode->next=head->next;  
  49.     head->next=NewNode;  
  50. }  
  51.   
  52. void PopFront(Node *head,int *data)  
  53. {  
  54.     assert(data);  
  55.     assert(head);  
  56.     if(IsEmpty(head))  
  57.     {  
  58.         printf("empty linkn");  
  59.         return ;  
  60.     }  
  61.     Node *del=head->next;  
  62.     *data=del->data;  
  63.     head->next=del->next;  
  64.     free(del);  
  65.     del=NULL;  
  66. }  
  67.   
  68. void DisplayLink(Node *head)  
  69. {  
  70.     assert(head);  
  71.     Node *cur=head->next;  
  72.     while(cur)  
  73.     {  
  74.         printf("%d ",cur->data);  
  75.         cur=cur->next;  
  76.     }  
  77.     printf("n");  
  78. }  
  79.   
  80. void DestroyLink(Node *head)  
  81. {  
  82.     int data=0;  
  83.     assert(head);  
  84.     while(!IsEmpty(head))  
  85.     {  
  86.         PopFront(head,&data);  
  87.     }  
  88.     free(head);  
  89. }  
  90.   
  91. void *product_run(void *arg)  
  92. {  
  93.     int data=0;  
  94.     Node *head=(Node *)arg;  
  95.     while(1)  
  96.     {  
  97.         usleep(100000);  
  98.         data=rand()%1000;  
  99.         pthread_mutex_lock(&mylock);  
  100.         PushFront(head,data);  
  101.         pthread_mutex_unlock(&mylock);  
  102.         pthread_cond_signal(&mycond);  
  103.         printf("product is done,data=%dn",data);  
  104.     }  
  105. }  
  106.   
  107. void *consumer_run(void *arg)  
  108. {  
  109.     int data=0;  
  110.     Node *head=(Node *)arg;  
  111.     while(1)  
  112.     {  
  113.         pthread_mutex_lock(&mylock);  
  114.         while(IsEmpty(head))  
  115.         {  
  116.             pthread_cond_wait(&mycond,&mylock);  
  117.         }  
  118.         PopFront(head,&data);  
  119.         pthread_mutex_unlock(&mylock);  
  120.         printf("consumer is done,data=%dn",data);  
  121.     }  
  122. }  
  123.   
  124. void testprocon()  
  125. {  
  126.     Node *head=NULL;  
  127.     InitLink(&head);  
  128.     pthread_t tid1;  
  129.     pthread_t tid2;  
  130.     pthread_create(&tid1,NULL,product_run,(void *)head);  
  131.     pthread_create(&tid2,NULL,consumer_run,(void *)head);  
  132.   
  133.     pthread_join(tid1,NULL);  
  134.     pthread_join(tid2,NULL);  
  135.     DestroyLink(head);  
  136.     pthread_mutex_destroy(&mylock);  
  137.     pthread_cond_destroy(&mycond);  
  138.   
  139. }  
  140. int main()  
  141. {  
  142.     testprocon();  
  143.     return 0;  
  144. }  
  145.   
  146. Makefile  
  147. procon:procon.c  
  148.     gcc -o $@ $^ -lpthread  
  149. .PHONY:clean  
  150. clean:  
  151.     rm -f procon  


    

总结:

   条件变量用在某个线程需要在某种条件才去保护它将要操作的临界区的情况下,从而避免了线程不断轮询检查该条件是否成立而降低效率的情况,这是实现了效率提高。

  希望对读者有帮助吧~~~~

    

最后

以上就是淡淡星星为你收集整理的浅析linux下的条件变量的全部内容,希望文章能够帮你解决浅析linux下的条件变量所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(60)

评论列表共有 0 条评论

立即
投稿
返回
顶部