互斥锁是用来给资源上锁的,而条件变量是用来等待而不是用来上锁的。

条件变量用来自动阻塞一个线程,直到某特殊情况发生为止。

通常条件变量和互斥锁同时使用。

和条件变量使用有关的几个重要函数:

  1. int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *cond_attr);
  2. int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
  3. int pthread_cond_timewait(pthread_cond_t *cond,pthread_mutex *mutex,const timespec *abstime);
  4. int pthread_cond_destroy(pthread_cond_t *cond);
  5. int pthread_cond_signal(pthread_cond_t *cond);
  6. int pthread_cond_broadcast(pthread_cond_t *cond); //解除所有线程的阻塞

1. 初始化:

条件变量采用的数据类型是pthread_cond_t, 在使用之前必须要进行初始化, 这包括两种方式:

  • 静态: 可以把常量PTHREAD_COND_INITIALIZER给静态分配的条件变量.
  • 动态: pthread_cond_init函数, 是释放动态条件变量的内存空间之前, 要用pthread_cond_destroy对其进行清理.

#include <pthread.h>

int pthread_cond_init(pthread_cond_t *restrict cond, pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t *cond);

成功则返回0, 出错则返回错误编号.

当pthread_cond_init的attr参数为NULL时, 会创建一个默认属性的条件变量; 非默认情况以后讨论.

2. 等待条件:

#include <pthread.h>

int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restric mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict timeout);

成功则返回0, 出错则返回错误编号.

这两个函数分别是阻塞等待和超时等待.

等待条件函数等待条件变为真, 传递给pthread_cond_wait的互斥量对条件进行保护, 调用者把锁住的互斥量传递给函数. 函数把调用线程放到等待条件的线程列表上, 然后对互斥量解锁, 这两个操作是原子的. 这样便关闭了条件检查和线程进入休眠状态等待条件改变这两个操作之间的时间通道, 这样线程就不会错过条件的任何变化.

当pthread_cond_wait返回时, 互斥量再次被锁住.

3. 通知条件:

#include <pthread.h>

int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);

成功则返回0, 出错则返回错误编号.

这两个函数用于通知线程条件已经满足. 调用这两个函数, 也称向线程或条件发送信号. 必须注意, 一定要在改变条件状态以后再给线程发送信号.

条件变量使用示例

下面是个非常简单的例子,很好的演示了条件变量如何使用。

我将创建一个生产者线程,两个消费者线程,通过互斥量和条件变量同步他们的生产和消费操作。

需要注意的一个地方是,pthread_cond_wait操作必须传入一个条件变量和互斥量,线程先对互斥量上锁,然后再执行pthread_cond_wait,pthread_cond_wait会将互斥量解锁。

pthread_cond_wait在while循环中而不在if中的原因是,“可能被意外唤醒”,所以需要在唤醒之后再检查缓冲区。

  1. #include <stdio.h>
  2. #include <pthread.h>
  3. #include <unistd.h>
  4.  
  5. pthread_cond_t condc,condp;
  6. pthread_mutex_t the_mutex;
  7.  
  8. unsigned int buffer = ;
  9. const int MAX = ;
  10.  
  11. void *producer(void *ptr){
  12. for(int i = ; i < MAX; i++){
  13. pthread_mutex_lock(&the_mutex);
  14. while(buffer != ) pthread_cond_wait(&condp, &the_mutex);
  15. sleep();
  16. buffer = i;
  17. printf("producer pthread produce one production %d.\n", i);
  18. pthread_cond_broadcast(&condc);//唤醒两个消费者线程
  19. pthread_mutex_unlock(&the_mutex);
  20. }
  21. pthread_exit();
  22. }
  23.  
  24. void *consumer1(void *ptr){
  25. for(int i = ; i < MAX; i++){
  26. pthread_mutex_lock(&the_mutex);
  27. while(buffer == ) pthread_cond_wait(&condc, &the_mutex);
  28. printf("consumer1 pthread consume one production %d.\n", buffer);
  29. buffer = ;
  30. pthread_cond_signal(&condp);
  31. pthread_mutex_unlock(&the_mutex);
  32. }
  33. pthread_exit();
  34. }
  35. void *consumer2(void *ptr){
  36. for(int i = ; i < MAX; i++){
  37. pthread_mutex_lock(&the_mutex);
  38. while(buffer == ) pthread_cond_wait(&condc, &the_mutex);
  39. printf("consumer2 pthread consume one production %d.\n", buffer);
  40. buffer = ;
  41. pthread_cond_signal(&condp);
  42. pthread_mutex_unlock(&the_mutex);
  43. }
  44. pthread_exit();
  45. }
  46.  
  47. int main(void){
  48. pthread_t pro, con1, con2;
  49. pthread_mutex_init(&the_mutex,);
  50. pthread_cond_init(&condc,);
  51. pthread_cond_init(&condp,);
  52. pthread_create(&con1, , consumer1, );
  53. pthread_create(&pro, , producer, );
  54. pthread_create(&con2, , consumer2, );
  55. pthread_join(pro, );
  56. pthread_join(con1, );
  57. pthread_join(con2, );
  58. pthread_cond_destroy(&condc);
  59. pthread_cond_destroy(&condp);
  60. pthread_mutex_destroy(&the_mutex);
  61. return ;
  62. }

运行结果

Linux线程同步——条件变量的更多相关文章

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

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

  2. pThreads线程(三) 线程同步--条件变量

    条件变量(Condition Variables) 参考资料:http://game-lab.org/posts/posix-thread-cn/#5.1 条件变量是什么? 条件变量为我们提供了另一种 ...

  3. linux线程同步(2)-条件变量

    一.概述                                                    上一篇,介绍了互斥量.条件变量与互斥量不同,互斥量是防止多线程同时访问共享的互斥变量来保 ...

  4. 【转】 Linux 线程同步的三种方法

    线程的最大特点是资源的共享性,但资源共享中的同步问题是多线程编程的难点.linux下提供了多种方式来处理线程同步,最常用的是互斥锁.条件变量和信号量. 一.互斥锁(mutex) 通过锁机制实现线程间的 ...

  5. Java线程:条件变量、原子量、线程池等

    一.条件变量 条件变量实现了java.util.concurrent.locks.Condition接口,条件变量的实例化就是通过一个Lock对象上调用newCondition()方法获得的,这样条件 ...

  6. linux 线程同步(二)

    信号量 信号量是相互排斥锁的升级版把相互排斥锁中1变成了n.举个简单的样例:如果如今有10个人,有一部手机.这10个人都竞争来使用手机打电话这就是相互排斥锁.对于信号量,如今可能是有4部手机,这10个 ...

  7. Linux线程同步:条件变量

    条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用.使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化.一旦其它 ...

  8. Linux 线程同步的三种方法(互斥锁、条件变量、信号量)

    互斥锁 #include <cstdio> #include <cstdlib> #include <unistd.h> #include <pthread. ...

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

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

随机推荐

  1. 合服导致 globalserver 起不来的问题

    globalserver 报错 RMIInitArmyBackObject InitError 根据报错信息一路追查下来,发现某个帮派的数据解析 json 的时候报错.监视变量,找出这段字符串,大致结 ...

  2. debug 工具

    git blame 查看某个文件的修改记录  二分查找确定 bug 来源 启动  输入 git bisect start,启动流程 输入 git bisect bad,标记当前是错误的 输入 gi ...

  3. PostgreSQL 数据库错误代码解释

    PostgreSQL 服务器发出的所有消息都赋予了五个字符 的错误代码, 这些代码遵循 SQL 的 "SQLSTATE" 代码的习惯.需要知道发生了什么错误条件的应用通常应该测试错 ...

  4. 解决ORA-21561: OID generation failed

    解决ORA-21561 在linux上使用sqlplus连接oracle数据库 [root@china ~]# sqlplus test/test@ORCL SQL Production :: Cop ...

  5. 用postman做接口测试实例

    使用postman做接口测试,可以选择请求方式,可以直接输入参数和header,可以编写测试结果的代码,判断是否通过测试 下图为填写接口测试地址.填写接口的参数,点击send发送请求 其中,Param ...

  6. JavaScript 闭包解决计数器问题

    JavaScript 闭包解决计数器问题 var add = (function () { var counter = 0; return function () {return counter += ...

  7. Docker学习--Linux基础准备篇

    1.docker命令不需要附带敲sudo的解决办法 由于docker daemon需要绑定到主机的Unix socket而不是普通的TCP端口,而Unix socket的属主为root用户,所以其他用 ...

  8. redis允许内网访问

    如题有A.B两台服务器. A服务器上装有reis,内网IP:192.168.0.1 B服务器需要访问A服务器上的redis 一.修改A服务器上redis.conf文件 bind 192.168.0.1 ...

  9. 在Mac OS X上启用Apache和PHP

    因为Mac OS X上都已自带了Apache和PHP,所以都无需进行安装,只要按照自己的需要进行设置即可. 找到httpd.conf文件,并用编辑器打开. 加载PHP模块.找到 #LoadModule ...

  10. Django的视图系统

    视图(views)概述 在前几篇文章中介绍了,client端通过http请求——去url的路由找到相应的视图函数——触发视图函数——再去modes取数据——取到数据后——再通过创建模——views函数 ...