条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用。使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化。一旦其它的某个线程改变了条件变量,它将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程。这些线程将重新锁定互斥锁并重新测试条件是否满足。一般说来,条件变量被用来进行线承间的同步。

 

1.条件变量的结构为pthread_cond_t (相当于windows中的事件的作用)

 

2.条件变量的初始化

      int pthread_cond_init __P ((pthread_cond_t *__cond,__const pthread_condattr_t *__cond_attr));

  其中cond是一个指向结构pthread_cond_t的指针,cond_attr是一个指向结构pthread_condattr_t的指针。结构pthread_condattr_t是条件变量的属性结构,和互斥锁一样我们可以用它来设置条件变量是进程内可用还是进程间可用,默认值是PTHREAD_ PROCESS_PRIVATE,即此条件变量被同一进程内的各个线程使用。注意初始化条件变量只有未被使用时才能重新初始化或被释放。

 

3.条件变量的释放

释放一个条件变量的函数为pthread_cond_ destroy(pthread_cond_t cond)

 

4.条件变量的等待

      (1)函数pthread_cond_wait()使线程阻塞在一个条件变量上。它的函数原型为:

  extern int pthread_cond_wait_P ((pthread_cond_t *__cond,pthread_mutex_t *__mutex));

  线程解开mutex指向的锁并被条件变量cond阻塞。线程可以被函数pthread_cond_signal和函数pthread_cond_broadcast唤醒,但是要注意的是,条件变量只是起阻塞和唤醒线程的作用,具体的判断条件还需用户给出,例如一个变量是否为0等等,这一点我们从后面的例子中可以看到。线程被唤醒后,它将重新检查判断条件是否满足,如果还不满足,一般说来线程应该仍阻塞在这里,被等待被下一次唤醒。这个过程一般用while语句实现。

  (2)另一个用来阻塞线程的函数是pthread_cond_timedwait(),它的原型为:

  extern int pthread_cond_timedwait_P (pthread_cond_t *__cond,

                                                                    pthread_mutex_t *__mutex, __const struct timespec *__abstime);

  它比函数pthread_cond_wait()多了一个时间参数,经历abstime段时间后,即使条件变量不满足,阻塞也被解除。



5.条件变量的解除改变

      函数pthread_cond_signal()的原型为:

  extern int pthread_cond_signal_P ((pthread_cond_t *__cond));

  它用来释放被阻塞在条件变量cond上的一个线程。多个线程阻塞在此条件变量上时,哪一个线程被唤醒是由线程的调度策略  所决定的。要注意的是,必须用保护条件变量的互斥锁来保护这个函数,否则条件满足信号又可能在测试条件和调用pthread_cond_wait函数之间被发出,从而造成无限制的等待。

 

6.下面是使用函数pthread_cond_wait()和函数pthread_cond_signal()的一个简单的例子。

pthread_mutex_t count_lock;

pthread_cond_t count_nonzero;

unsigned count;

decrement_count () {

pthread_mutex_lock (&count_lock);

while(count==0) 

pthread_cond_wait( &count_nonzero, &count_lock);

count=count -1;

pthread_mutex_unlock (&count_lock);

}



increment_count(){

pthread_mutex_lock(&count_lock);

if(count==0)

pthread_cond_signal(&count_nonzero);

count=count+1;

pthread_mutex_unlock(&count_lock);

}

  

count值为0时,decrement函数在pthread_cond_wait处被阻塞,并打开互斥锁count_lock。此时,当调用到函数increment_count时,pthread_cond_signal()函数改变条件变量,告知decrement_count()停止阻塞。



有的时候仅仅依靠锁住共享资源来使用它是不够的。有时候共享资源只有某些状态的时候才能够使用。比方说,某个线程如果要从堆栈中读取数据,那么如果栈中没有数据就必须等待数据被压栈。这种情况下的同步使用互斥锁

是不够的。另一种同步的方式--条件变量,就可以使用在这种情况下。

条件变量的使用总是和互斥锁及共享资源联系在一起的。线程首先锁住互斥锁,然后检验共享资源的状态是否处于可使用的状态。如果不是,那么线程就要等待条件变量。要指向这样的操作就必须在等待的时候将互斥锁解锁,以

便其他线程可以访问共享资源并改变其状态。它还得保证从等到得线程返回时互斥体是被上锁得。当另一个线程改变了共享资源的状态时,它就要通知正在等待条件变量的线程,使之重新变回被互斥锁阻塞的线程。

请看下面的例子:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <pthread.h>
  4. pthread_mutex_t cond_mutex=PTHREAD_MUTEX_INITIALIZER;
  5. pthread_cond_t cond_var=PTHREAD_COND_INITIALIZER;
  6. void* function_cond1();
  7. void* function_cond2();
  8. int count=0;
  9. #define COUNT_DONE  10
  10. #define COUNT_HALT1  3
  11. #define COUNT_HALT2  6
  12. int main()
  13. {
  14. pthread_t thread1,thread2;
  15. pthread_create(&thread1,NULL,function_cond1,NULL);
  16. pthread_create(&thread2,NULL,function_cond2,NULL);
  17. pthread_join(thread1,NULL);
  18. pthread_join(thread2,NULL);
  19. printf("Final count: %d\n",count);
  20. return 0;
  21. }
  22. void* function_cond1()
  23. {
  24. for(;;)
  25. {
  26. pthread_mutex_lock(&cond_mutex);
  27. pthread_cond_wait(&cond_var,&cond_mutex);
  28. count++;
  29. printf("Counter value functionCount1: %d\n",count);
  30. pthread_mutex_unlock(&cond_mutex);
  31. if(count>=COUNT_DONE) return ;
  32. }
  33. }
  34. void* function_cond2()
  35. {
  36. for(;;)
  37. {
  38. pthread_mutex_lock(&cond_mutex);
  39. if(count<COUNT_HALT1||count>COUNT_HALT2)
  40. {
  41. // Condition of if statement has been met.
  42. // Signal to free waiting thread by freeing the mutex.
  43. // Note: functionCount1() is now permitted to modify "count".
  44. pthread_cond_signal(&cond_var);
  45. }
  46. else
  47. {
  48. count++;
  49. printf("Counter value functionCount2: %d\n",count);
  50. }
  51. pthread_mutex_unlock(&cond_mutex);
  52. if(count>=COUNT_DONE) return ;
  53. }
  54. }

结果:

两个线程同时运行,当在count<COUNT_HALT1||count>COUNT_HALT2的时候,线程1是一直等待的。只有线程2条件到达的时候,调用pthread_cond_signal(&cond_var);通知

线程1,pthread_cond_wait(&cond_var,&cond_mutex);




原文:http://blog.csdn.net/dlutbrucezhang/article/details/8830739

POSIX多线程编程-条件变量pthread_cond_t的更多相关文章

  1. Linux多线程编程详细解析----条件变量 pthread_cond_t

    Linux操作系统下的多线程编程详细解析----条件变量 1.初始化条件变量pthread_cond_init #include <pthread.h> int pthread_cond_ ...

  2. POSIX 多线程编程及理解

    最近开发基于ZYNQ的嵌入式linux程序,涉及到多线程使用,将一些内容整理如下: POSIX多线程编程最为基础和重要的可以分为两部分: 线程操作-Thread Management 线程同步-Syn ...

  3. [posix]Posix多线程编程

    就不排版了,可以到原作者博客下看 转自:http://www.cnblogs.com/zhangsf/archive/2013/09/09/3309867.html 目录表  摘要 译者序 Pthre ...

  4. linux多线程-互斥&条件变量与同步

    多线程代码问题描述 我们都知道,进程是操作系统对运行程序资源分配的基本单位,而线程是程序逻辑,调用的基本单位.在多线程的程序中,多个线程共享临界区资源,那么就会有问题: 比如 #include < ...

  5. C++并发编程 条件变量 condition_variable,线程安全队列示例

    1. 背景 c++11中提供了对线程与条件变量的更好支持,对于写多线程程序方便了很多. 再看c++并发编程,记一下学习笔记. 2. c++11 提供的相关api 3.1 wait wait用于无条件等 ...

  6. Linux系统编程—条件变量

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

  7. 条件变量pthread_cond_t怎么用

    #include <pthread.h> #include <stdio.h> #include <stdlib.h> pthread_mutex_t mutex ...

  8. linux Posix线程同步(条件变量) 实例

    条件变量:与互斥量一起使用,暂时申请不到某资源时进入条件阻塞等待,当资源具备时线程恢复运行 应用场合:生产线程不断的生产资源,并通知产生资源的条件,消费线程在没有资源情况下进入条件等待,一直等到条件信 ...

  9. C++11并行编程-条件变量(condition_variable)详细说明

    <condition_variable >头文件主要包含有类和函数相关的条件变量. 包括相关类 std::condition_variable和 std::condition_variab ...

随机推荐

  1. ps 快速替换背景颜色

    1.打开图片: 点击工具栏上的"选择"--色彩范围--按[delete]

  2. Go:go程序报错Cannot run program "C:\Users\dell\AppData\Local\Temp\___go_build_hello_go.exe" (in directory "…………"):该版本的 %1 与你运行的 Windows 版本不兼容。

    问题截图 在go语言编译的时候,如果只是单单编译一个文件的话,package必须是main,意味着是可以单独编译的. 解决办法 修改为 package main 就可以 再次运行就可以啦. 文章转载至 ...

  3. MOS管开关电路笔记

    1.MOS管开关电路是利用MOS管栅极(g)控制MOS管源极(s)和漏极(d)通断的原理构造的电路.MOS管分为N沟道与P沟道,所以开关电路也主要分为两种.P沟道或N沟道共四种类型,但实际应用的只有增 ...

  4. MySQL | Xtrabackup 安装

    rpm方式安装 # xtrabackup 2.4.8 安装包 wget https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup- ...

  5. ARTS第十三周(阅读Tomcat源码)

    1.Algorithm:每周至少做一个 leetcode 的算法题2.Review:阅读并点评至少一篇英文技术文章3.Tip:学习至少一个技术技巧4.Share:分享一篇有观点和思考的技术文章 考研真 ...

  6. C语言:模拟密码输入显示星号

    一个安全的程序在用户输入密码时不应该显示密码本身,而应该回显星号或者点号,例如······或******,这在网页.PC软件.ATM机.POS机上经常看到.但是C语言没有提供类似的功能,控制台上只能原 ...

  7. 高校表白App-团队冲刺第九天

    今天要做什么 在Fragment首页加上轮转播报,点击图片进入相应连接 做了什么 功能实现,通过连接第三方库来进行实现,比较简单.(url就可以) 遇到的问题 在调用以前的工具类时,有点小问题,发现以 ...

  8. MySQL用B+树(而不是B树)做索引的原因

    众所周知,MySQL的索引使用了B+树的数据结构.那么为什么不用B树呢? 先看一下B树和B+树的区别. B树 维基百科对B树的定义为"在计算机科学中,B树(B-tree)是一种树状数据结构, ...

  9. Python_结合Re正则模块爬虫

    ##### 爬取古诗文import reimport requestsdef parse_page(url): headers = { 'User-Agent':'Mozilla/5.0 (Windo ...

  10. 【LeetCode】144. 二叉树的前序遍历

    144. 二叉树的前序遍历 知识点:二叉树:递归:Morris遍历 题目描述 给你二叉树的根节点 root ,返回它节点值的 前序 遍历. 示例 输入:root = [1,null,2,3] 输出:[ ...