2019独角兽企业重金招聘Python工程师标准>>>

前一节中我们讲述了如何使用互斥锁来实现线程间数据的共享和通信,互斥锁一个明显的缺点是它只有两种状态:锁定和非锁定。而条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用。使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化。一旦其它的某个线程改变了条件变量,它将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程。这些线程将重新锁定互斥锁并重新测试条件是否满足。一般说来,条件变量被用来进行线程间的同步。

1. 相关操作

条件变量和互斥锁一样,都有静态动态两种创建方式

静态方式

静态方式使用PTHREAD_COND_INITIALIZER常量,如: pthread_cond_t  cond = PTHREAD_COND_INITIALIZER

动态方式

int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr)

使用 cond_attr 指定的属性初始化条件变量 cond,当 cond_attr为 NULL时,使用缺省的属性。LinuxThreads实现条件变量不支持属性,因此 cond_attr参数实际被忽略。

注销

int pthread_cond_destroy(pthread_cond_t *cond)

注销一个条件变量需要调用pthread_cond_destroy(),只有在没有线程在该条件变量上等待的时候才能注销这个条件变量,否则返回EBUSY。因为Linux实现的条件变量没有分配什么资源,所以注销动作只包括检查是否有等待线程。

2. 等待和激发

等待

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)

这个函数是POSIX线程信号发送系统的核心,也是最难以理解的部分,过程为:解锁-wait-收到信号-加锁-返回。

设置时间的等待

int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, conststruct timespec *abstime)

pthread_cond_timedwait和 pthread_cond_wait一样,自动解锁互斥量及等待条件变量,但它还限定了等待时间。如果在 abstime指定的时间内 cond未触发,互斥量 mutex被重新加锁,并返回错误 ETIMEDOUT。abstime参数指定一个绝对时间,时间原点与 time和 gettimeofday相同:abstime = 0表示 1970-1- 1 00:00:00 GMT。

pthread_cond_timedwait 函数出错时返回下列错误代码:

ETIMEDOUT   abstime 指定的时间超时时,条件变量未触发

EINTR       pthread_cond_timedwait 被触发中断

激发

int pthread_cond_signal(pthread_cond_t *cond);

int pthread_cond_broadcast(pthread_cond_t *cond);

激发条件有两种形式,pthread_cond_signal()激活一个等待该条件的线程,多个线程阻塞在此条件变量上时,哪一个线程被唤醒是由线程的调度策略所决定的;而pthread_cond_broadcast()则激活所有等待线程,这些线程被唤醒后将再次竞争相应的互斥锁。

要注意的是,必须用保护条件变量的互斥锁来保护激活函数,否则条件满足信号有可能在测试条件和调用pthread_cond_wait()函数之间被发出,从而造成无限制的等待。

二、互斥量与条件变量

问题:从本质上说互斥量就是一把锁,互斥量串行执行,能确保每次只有一个线程访问。互斥量是线程程序必需的工具,但它们并非万能的。例如,如果线程正在轮询等待共享数据内某个条件出现,那会发生什么呢?它可以重复对互斥对象锁定和解锁,每次都会检查共享数据结构,以查找某个值。但这是在浪费时间和资源,而且这种繁忙查询的效率非常低。同样,在每次检查之间让线程短暂地进入睡眠,比如睡眠3s,但是因此线程代码就无法最快作出响应。

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

三 . 应用  

设有两个共享的变量 x 和 y,通过互斥量 mut 保护,当 x > y 时,条件变量 cond 被触发。

int x,y;

int x,y;

pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

等待直到 x > y 的执行流程:

pthread_mutex_lock(&mut);

while (x <= y) {

pthread_cond_wait(&cond, &mut);

}

/* 对 x、y 进行操作 */

pthread_mutex_unlock(&mut);

对 x 和 y 的修改可能导致 x > y,应当触发条件变量:

pthread_mutex_lock(&mut);

/* 修改 x、y */

if (x > y) pthread_cond_broadcast(&cond);

pthread_mutex_unlock(&mut);

如果能够确定最多只有一个等待线程需要被唤醒(例如,如果只有两个线程通过 x、y 通信),则使用 pthread_cond_signal 比 pthread_cond_broadcast 效率稍高一些。如果不能确定,应当用 pthread_cond_broadcast。

要等待在 5 秒内 x > y,这样处理:

struct timeval now;

struct timespec timeout;

int retcode;

pthread_mutex_lock(&mut);

gettimeofday(&now);

timeout.tv_sec = now.tv_sec + 5;

timeout.tv_nsec = now.tv_usec * 1000;

retcode = 0;

while (x <= y && retcode != ETIMEDOUT) {

retcode = pthread_cond_timedwait(&cond, &mut, &timeout);

}

if (retcode == ETIMEDOUT) {

/* 发生超时 */

} else {

/* 操作 x 和  y */

}

pthread_mutex_unlock(&mut);

转载于:https://my.oschina.net/wanneng/blog/661101

Linux多线程编程四(条件变量)相关推荐

  1. java suprious wakeup_多线程编程中条件变量和的spurious wakeup 虚假唤醒

    1. 概述 条件变量(condition variable)是利用共享的变量进行线程之间同步的一种机制.典型的场景包括生产者-消费者模型,线程池实现等. 对条件变量的使用包括两个动作: 1)线程等待某 ...

  2. C++多线程编程(2) 条件变量与原子操作

    条件变量 条件变量是c++11 提供的另一种用于等待的同步机制,它能阻塞一个或者多个线程,直到收到另外一个线程发出的通知或者超时,才会唤醒当前阻塞的线程,条件变量需要和互斥量配合使用,C++11提供两 ...

  3. python多线程编程(5): 条件变量同步

    From: http://www.cnblogs.com/holbrook/archive/2012/03/13/2394811.html 互斥锁是最简单的线程同步机制,Python提供的Condit ...

  4. Linux多线程编程---线程间同步(互斥锁、条件变量、信号量和读写锁)

    本篇博文转自http://zhangxiaoya.github.io/2015/05/15/multi-thread-of-c-program-language-on-linux/ Linux下提供了 ...

  5. ZT 为什么pthread_cond_t要和pthread_mutex_t同时使用 || pthread/Linux多线程编程

    为什么线程同步的时候pthread_cond_t要和pthread_mutex_t同时使用 (2009-10-27 11:07:23) 转载▼ 标签: 杂谈 分类: 计算机 举一个例子(http:// ...

  6. Linux 多线程编程(实现生产者消费者模型)

    Linux 多线程编程 线程分类 线程按照其调度者可以分为用户级线程和内核级线程两种. 内核级线程 在一个系统上实现线程模型的方式有好几种,因内核和用户空间提供的支持而有一定程度的级别差异.最简单的模 ...

  7. linux线程 ppt,Linux多线程编程多核编程.ppt

    <Linux多线程编程多核编程.ppt>由会员分享,可在线阅读,更多相关<Linux多线程编程多核编程.ppt(28页珍藏版)>请在装配图网上搜索. 1.Linux多线程编程, ...

  8. 多核程序设计 linux,多核程序设计Linux多线程编程.ppt

    Linux多线程编程,IEEE POSIX 标准 p1003.1c (Pthreads) 定义了处理线程的一系列C 语言类型的API. 在Linux中,线程一般被认为是"轻量级的进程&quo ...

  9. c/c++ Linux多线程编程

    Linux多线程编程 线程概念 线程是指运行中的程序的调度单位.一个线程指的是进程中一个单一顺序的控制流,也被称为轻量级线程.它是系统独立调度和分配的基本单位.同一进程中的多个线程将共享该系统中的全部 ...

最新文章

  1. 读服务器文件,读取服务器文件
  2. 10.app后端选择什么开发语言
  3. Azkaban-solo模式-安装
  4. java中bean的定义有哪些_详解Java的Spring框架中bean的定义以及生命周期
  5. 飞行姿态角度表示: heading pitch roll
  6. 可蠕虫 DarkRadiation 勒索软件瞄准 Linux 和 Docker 实例
  7. layUI使用table.reload时出现了两次请求问题
  8. JSTL 核心标签库标签共有13个
  9. C#读取匿名对象的属性值的方法总结
  10. 最新酷盒工具箱iApp源码9.5版+功能很多
  11. blender中常用快捷键的总结
  12. 公司规章制度制度(受不了)
  13. 使用Selenium获取当当网异步加载的部分分类数据
  14. 发展你的GDS的应用技术
  15. OpenHarmony WLAN HDI 源码学习
  16. 10-解决win10系统更新后开机变慢的问题
  17. 1567. 乘积为正数的最长子数组长度 ●●
  18. 【Oracle数据库基础学习】
  19. 2018中国汽车企业排行榜TOP10
  20. SUSE史上首位女性CEO Melissa Di Donato,不止有“三把火”

热门文章

  1. [转载]在Eclipse CDT中编译含有多个main函数的项目
  2. 数据库设计指南(四)保证数据的完整性
  3. 无法链接到SQL Server远程服务器的解决
  4. 自建git服务器连接Pycharm系列二:在centos7上搭建git服务器
  5. 揭秘天猫双十一背后的那位贤内助
  6. mixed content 混合内容
  7. ASP.NET的简单与面向对象开发
  8. 管道命令 (pipe)
  9. 仿百度GIF验证码 GIFEncoder 跳动验证码 随机背景色、颜色、字体、子大小、偏移、干扰线等...
  10. C#生成CHM文件(外篇使用hha.dll)