pthread_cond_wait()用法分析

很久没看APUE,今天一位朋友问道关于一个mutex的问题,又翻到了以前讨论过的东西,为了不让自己忘记,把曾经的东西总结一下。
先大体看下网上很多地方都有的关于pthread_cond_wait()的说明:

条件变量
         
条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起;另一个线程使"条件成立"(给出条件成立信号)。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。
         1.
  创建和注销     
    
条件变量和互斥锁一样,都有静态动态两种创建方式,静态方式使用PTHREAD_COND_INITIALIZER常量,如下:        pthread_cond_t  
cond=PTHREAD_COND_INITIALIZER          
  动态方式调用pthread_cond_init()函数,API定义如下:     
  int   pthread_cond_init(pthread_cond_t   *cond,  
pthread_condattr_t   *cond_attr)         
  尽管POSIX标准中为条件变量定义了属性,但在LinuxThreads中没有实现,因此cond_attr值通常为NULL,且被忽略。
         
注销一个条件变量需要调用pthread_cond_destroy(),只有在没有线程在该条件变量上等待的时候才能注销这个条件变量,否则返回EBUSY。因为Linux实现的条件变量没有分配什么资源,所以注销动作只包括检查是否有等待线程。API定义如下:
      int   pthread_cond_destroy(pthread_cond_t  
*cond)       
     2.  
等待和激发         int  
pthread_cond_wait(pthread_cond_t   *cond,   pthread_mutex_t  
*mutex)      int
  pthread_cond_timedwait(pthread_cond_t   *cond,  
pthread_mutex_t   *mutex,   const   struct   timespec  
*abstime)              
      
等待条件有两种方式:无条件等待pthread_cond_wait()和计时等待pthread_cond_timedwait(),其中计时等待方式如果在给定时刻前条件没有满足,则返回ETIMEOUT,结束等待,其中abstime以与time()系统调用相同意义的绝对时间形式出现,0表示格林尼治时间1970年1月1日0时0分0秒。
        
无论哪种等待方式,都必须和一个互斥锁配合,以防止多个线程同时请求pthread_cond_wait()(或pthread_cond_timedwait(),下同)的竞争条件(Race
 
Condition)。mutex互斥锁必须是普通锁(PTHREAD_MUTEX_TIMED_NP)或者适应锁(PTHREAD_MUTEX_ADAPTIVE_NP),且在调用pthread_cond_wait()前必须由本线程加锁(pthread_mutex_lock()),而在更新条件等待队列以前,mutex保持锁定状态,并在线程挂起进入等待前解锁。在条件满足从而离开pthread_cond_wait()之前,mutex将被重新加锁,以与进入pthread_cond_wait()前的加锁动作对应。
         
激发条件有两种形式,pthread_cond_signal()激活一个等待该条件的线程,存在多个等待线程时按入队顺序激活其中一个;而pthread_cond_broadcast()则激活所有等待线程。

现在来看一段典型的应用:看注释即可。

[cpp] view plaincopy

  1. #include <pthread.h>

  2. #include <unistd.h>
  3. static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;

  4. static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
  5. struct node {

  6. int n_number;

  7. struct node *n_next;

  8. } *head = NULL;
  9. /*[thread_func]*/

  10. static void cleanup_handler(void *arg)

  11. {

  12. printf("Cleanup handler of second thread./n");

  13. free(arg);

  14. (void)pthread_mutex_unlock(&mtx);

  15. }

  16. static void *thread_func(void *arg)

  17. {

  18. struct node *p = NULL;
  19. pthread_cleanup_push(cleanup_handler, p);

  20. while (1) {

  21. pthread_mutex_lock(&mtx);           //这个mutex主要是用来保证pthread_cond_wait的并发性

  22. while (head == NULL)   {               //这个while要特别说明一下,单个pthread_cond_wait功能很完善,为何这里要有一个while (head == NULL)呢?因为pthread_cond_wait里的线程可能会被意外唤醒,如果这个时候head != NULL,则不是我们想要的情况。这个时候,应该让线程继续进入pthread_cond_wait

  23. pthread_cond_wait(&cond, &mtx);         // pthread_cond_wait会先解除之前的pthread_mutex_lock锁定的mtx,然后阻塞在等待对列里休眠,直到再次被唤醒(大多数情况下是等待的条件成立而被唤醒,唤醒后,该进程会先锁定先pthread_mutex_lock(&mtx);,再读取资源

  24. //用这个流程是比较清楚的/*block-->unlock-->wait() return-->lock*/

  25. }

  26. p = head;

  27. head = head->n_next;

  28. printf("Got %d from front of queue/n", p->n_number);

  29. free(p);

  30. pthread_mutex_unlock(&mtx);             //临界区数据操作完毕,释放互斥锁

  31. }

  32. pthread_cleanup_pop(0);

  33. return 0;

  34. }
  35. int main(void)

  36. {

  37. pthread_t tid;

  38. int i;

  39. struct node *p;

  40. pthread_create(&tid, NULL, thread_func, NULL);   //子线程会一直等待资源,类似生产者和消费者,但是这里的消费者可以是多个消费者,而不仅仅支持普通的单个消费者,这个模型虽然简单,但是很强大

  41. /*[tx6-main]*/

  42. for (i = 0; i < 10; i++) {

  43. p = malloc(sizeof(struct node));

  44. p->n_number = i;

  45. pthread_mutex_lock(&mtx);             //需要操作head这个临界资源,先加锁,

  46. p->n_next = head;

  47. head = p;

  48. pthread_cond_signal(&cond);

  49. pthread_mutex_unlock(&mtx);           //解锁

  50. sleep(1);

  51. }

  52. printf("thread 1 wanna end the line.So cancel thread 2./n");

  53. pthread_cancel(tid);             //关于pthread_cancel,有一点额外的说明,它是从外部终止子线程,子线程会在最近的取消点,退出线程,而在我们的代码里,最近的取消点肯定就是pthread_cond_wait()了。关于取消点的信息,有兴趣可以google,这里不多说了

  54. pthread_join(tid, NULL);

  55. printf("All done -- exiting/n");

  56. return 0;

  57. }

pthread_cond_wait()用法分析,布布扣,bubuko.com

时间: 2024-08-24 03:17:48

pthread_cond_wait()用法分析的相关文章

java String.split()函数的用法分析

在java.lang包中有String.split()方法的原型是:public String[] split(String regex, int limit)split函数是用于使用特定的切割符(regex)来分隔字符串成一个字符串数组,函数返回是一个数组.在其中每个出现regex的位置都要进行分解.需要注意是有以下几点:(1)regex是可选项.字符串或正则表达式对象,它标识了分隔字符串时使用的是一个还是多个字符.如果忽略该选项,返回包含整个字符串的单一元素数组.(2)limit也是可选项.

PHP构造函数的用法分析

管理 随笔- 1 文章- 1 评论- 0 PHP构造函数的用法分析 PHP构造函数的声明与其它操作的声明一样,只是其名称必须是__construct( ).这是PHP5中的变化,以前的版本中,构造函数的名称必须与类名相同,这种在PHP5中仍然可以用,但现在以经很少有人用了,这样做的好处是可以使构造函数独立于类名,当类名发生改变时不需要改相应的构造函数名称了.为了向下兼容,如果一个类中没有名为__construct( )的方法,PHP将搜索一个php4中的写法,与类名相同名的构造方法.格式:fun

Request.Cookies用法分析

本文章介绍了Request.Cookies的基本语法和用法.并且通过示例分析了Request.Cookies的使用过程. Request.Cookies方法可以检索Cookies 集合中的值,Cookies 集合允许用户检索在 HTTP 请求中发送的 cookie 的值. Request.Cookies使用语法:Request.Cookies(cookie)[(key)|.attribute] Cookies是一种标记,由WEB服务器嵌入到用户浏览器中,以便识别用户,下次同一浏览器请求网页时,将

UIButton UIImage 用法分析

UIButton UIImage 用法分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 一.UIButton和UIImageView的区别 1.显示图片 1> UIImageView只能显示一种图片(图片默认会填充整个UIImageView)  im

display:Block 用法分析

根据CSS规范的规定,每一个网页元素都有一个display属性,用于确定该元素的类型,每一个元素都有默认的display属性值,比如div元素,它的默认display属性值为"block",成为"块级"元素(block-level):而span元素的默认display属性值为"inline",称为"行内"元素. 块级元素: 动占据一定矩形空间,可以通过设置高度.宽度.内外边距等属性,来调整的这个矩形的样子: 行内元素: 自己的

判断类是否存在函数class_exists用法分析

原文地址:判断类是否存在函数class_exists用法分析 如果我们要判断一个类是不是可以用,可以先使用class_exists函数来判断一下,下面来看几个例子. bool class_exists ( string $class_name [, bool $autoload = true ] ) 此功能是否给定的类被定义检查.this function checks whether or not the given class has been defined.返回true,如果class_

C#类中static变量用法分析

本文实例讲述了C#类中static变量用法.分享给大家供大家参考.具体分析如下: 先来看一段代码: 代码如下: using System; namespace Param { class Class1 { static int i = getNum(); int j = getNum(); static int num = 1; static int getNum() { return num; } [STAThread] static void Main(string[] args) { Co

.NET中的属性用法分析

GPS平台.网站建设.软件开发.系统运维,找森大网络科技!http://cnsendnet.taobao.com来自森大科技官方博客http://www.cnsendblog.com/index.php/?p=516 这篇文章主要介绍了.NET中的属性用法,分析了.NET中属性的功能.定义与具体用法,具有一定参考借鉴价值,需要的朋友可以参考下本文实例分析了.NET中的属性用法.分享给大家供大家参考.具体分析如下:1.What?什么是属性属性是对字段的封装.当类中有了一个字段以后,为了控制这个字段

(实用篇)php支付宝接口用法分析

本文实例讲述了php支付宝接口用法.分享给大家供大家参考.具体分析如下: 现在流行的网站支持平台,支付宝当仁不让的老大了,现在我们就来告诉你如何使用支付宝api来做第三方支付,把支付宝放到自己网站来, alipay_config.php配置程序如下: <?php */ //alipay_config.php 配置程序 $interfaceurl = "https://www.alipay.com/payto:"; $sitename = "网站名称"; $we