转:条件变量、pthread_cond_init
1.初始化条件变量pthread_cond_init
#include <pthread.h>
int pthread_cond_init(pthread_cond_t *cv,
const pthread_condattr_t *cattr);
返回值:函数成功返回0;任何其他返回值都表示错误
初始化一个条件变量。当参数cattr为空指针时,函数创建的是一个缺省的条件变量。否则条件变量的属性将由cattr中的属性值来决定。调用 pthread_cond_init函数时,参数cattr为空指针等价于cattr中的属性为缺省属性,只是前者不需要cattr所占用的内存开销。这个函数返回时,条件变量被存放在参数cv指向的内存中。
可以用宏PTHREAD_COND_INITIALIZER来初始化静态定义的条件变量,使其具有缺省属性。这和用pthread_cond_init函数动态分配的效果是一样的。初始化时不进行错误检查。如:
pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
不能由多个线程同时初始化一个条件变量。当需要重新初始化或释放一个条件变量时,应用程序必须保证这个条件变量未被使用。
2.阻塞在条件变量上pthread_cond_wait
#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *cv,
pthread_mutex_t *mutex);
返回值:函数成功返回0;任何其他返回值都表示错误
函数将解锁mutex参数指向的互斥锁,并使当前线程阻塞在cv参数指向的条件变量上。
被阻塞的线程可以被pthread_cond_signal函数,pthread_cond_broadcast函数唤醒,也可能在被信号中断后被唤醒。
pthread_cond_wait函数的返回并不意味着条件的值一定发生了变化,必须重新检查条件的值。
pthread_cond_wait函数返回时,相应的互斥锁将被当前线程锁定,即使是函数出错返回。
一般一个条件表达式都是在一个互斥锁的保护下被检查。当条件表达式未被满足时,线程将仍然阻塞在这个条件变量上。当另一个线程改变了条件的值并向条件变量发出信号时,等待在这个条件变量上的一个线程或所有线程被唤醒,接着都试图再次占有相应的互斥锁。
阻塞在条件变量上的线程被唤醒以后,直到pthread_cond_wait()函数返回之前条件的值都有可能发生变化。所以函数返回以后,在锁定相应的互斥锁之前,必须重新测试条件值。最好的测试方法是循环调用pthread_cond_wait函数,并把满足条件的表达式置为循环的终止条件。如:
pthread_mutex_lock();
while (condition_is_false)
pthread_cond_wait();
pthread_mutex_unlock();
阻塞在同一个条件变量上的不同线程被释放的次序是不一定的。
注意:pthread_cond_wait()函数是退出点,如果在调用这个函数时,已有一个挂起的退出请求,且线程允许退出,这个线程将被终止并开始执行善后处理函数,而这时和条件变量相关的互斥锁仍将处在锁定状态。
3.解除在条件变量上的阻塞pthread_cond_signal
#include <pthread.h>
int pthread_cond_signal(pthread_cond_t *cv);
返回值:函数成功返回0;任何其他返回值都表示错误
函数被用来释放被阻塞在指定条件变量上的一个线程。
必须在互斥锁的保护下使用相应的条件变量。否则对条件变量的解锁有可能发生在锁定条件变量之前,从而造成死锁。
唤醒阻塞在条件变量上的所有线程的顺序由调度策略决定,如果线程的调度策略是SCHED_OTHER类型的,系统将根据线程的优先级唤醒线程。
如果没有线程被阻塞在条件变量上,那么调用pthread_cond_signal()将没有作用。
4.阻塞直到指定时间pthread_cond_timedwait
#include <pthread.h>
#include <time.h>
int pthread_cond_timedwait(pthread_cond_t *cv,
pthread_mutex_t *mp, const structtimespec * abstime);
返回值:函数成功返回0;任何其他返回值都表示错误
函数到了一定的时间,即使条件未发生也会解除阻塞。这个时间由参数abstime指定。函数返回时,相应的互斥锁往往是锁定的,即使是函数出错返回。
注意:pthread_cond_timedwait函数也是退出点。
超时时间参数是指一天中的某个时刻。使用举例:
pthread_timestruc_t to;
to.tv_sec = time(NULL) + TIMEOUT;
to.tv_nsec = 0;
超时返回的错误码是ETIMEDOUT。
5.释放阻塞的所有线程pthread_cond_broadcast
#include <pthread.h>
int pthread_cond_broadcast(pthread_cond_t *cv);
返回值:函数成功返回0;任何其他返回值都表示错误
函数唤醒所有被pthread_cond_wait函数阻塞在某个条件变量上的线程,参数cv被用来指定这个条件变量。当没有线程阻塞在这个条件变量上时,pthread_cond_broadcast函数无效。
由于pthread_cond_broadcast函数唤醒所有阻塞在某个条件变量上的线程,这些线程被唤醒后将再次竞争相应的互斥锁,所以必须小心使用pthread_cond_broadcast函数。
6.释放条件变量pthread_cond_destroy
#include <pthread.h>
int pthread_cond_destroy(pthread_cond_t *cv);
返回值:函数成功返回0;任何其他返回值都表示错误
释放条件变量。
注意:条件变量占用的空间并未被释放。
7.唤醒丢失问题
在线程未获得相应的互斥锁时调用pthread_cond_signal或pthread_cond_broadcast函数可能会引起唤醒丢失问题。
唤醒丢失往往会在下面的情况下发生:
- 一个线程调用pthread_cond_signal或pthread_cond_broadcast函数;
- 另一个线程正处在测试条件变量和调用pthread_cond_wait函数之间;
- 没有线程正在处在阻塞等待的状态下。
转:条件变量、pthread_cond_init的更多相关文章
- Linux 多线程条件变量同步
条件变量是线程同步的另一种方式,实际上,条件变量是信号量的底层实现,这也就意味着,使用条件变量可以拥有更大的自由度,同时也就需要更加小心的进行同步操作.条件变量使用的条件本身是需要使用互斥量进行保护的 ...
- Linux多线程编程详细解析----条件变量 pthread_cond_t
Linux操作系统下的多线程编程详细解析----条件变量 1.初始化条件变量pthread_cond_init #include <pthread.h> int pthread_cond_ ...
- Linux多线程实践(8) --Posix条件变量解决生产者消费者问题
Posix条件变量 int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr); int pthread_co ...
- linux Posix线程同步(条件变量) 实例
条件变量:与互斥量一起使用,暂时申请不到某资源时进入条件阻塞等待,当资源具备时线程恢复运行 应用场合:生产线程不断的生产资源,并通知产生资源的条件,消费线程在没有资源情况下进入条件等待,一直等到条件信 ...
- linux 条件变量与线程池
条件变量Condition Variables 概述 1. 条件变量提供了另外一种线程同步的方式.如果没有条件变量,程序需要使用线程连续轮询(可能在临界区critical section内)方式检查条 ...
- Linux操作系统下的多线程编程详细解析----条件变量
条件变量通过允许线程阻塞和等待另一个线程发送信号的方法,弥补了互斥锁(Mutex)的不足. 1.初始化条件变量pthread_cond_init #include <pthread.h> ...
- muduo网络库源码学习————条件变量
muduo里的CountDownLatch类实际上是对条件变量condition进行的封装,既可以用于所有子线程等待主线程发起 "起跑" ,也可以用于主线程等待子线程初始化完毕才开 ...
- linux网络编程-posix条件变量(40)
举一个列子来说明条件变量: 假设有两个线程同时访问全局变量n,初始化值是0, 一个线程进入临界区,进行互斥操作,线程当n大于0的时候才执行下面的操作,如果n不大于0,该线程就一直等待. 另外一个线程也 ...
- Linux线程同步:条件变量
条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用.使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化.一旦其它 ...
随机推荐
- java.io.IOException: Unable to open sync connection!的解决方案
在学习Android的时候,经常是使用手机调试程序,很方便,后来 在使用手机调试程序的时候出现了 [2012-03-08 11:27:43 - Tea_marsListActivity] ------ ...
- 从零开始学C++之构造函数与析构函数(三):深拷贝与浅拷贝、空类
一.深拷贝与浅拷贝 说得简单点,假设一个类有指针成员,如果在拷贝的时候顺带连指针指向的内存也分配了,就称为深拷贝:如果只是分配指针本身的内存,那就是浅拷贝.浅拷贝造成的问题是有两个指针指向同块内存,d ...
- 类classthe Meta-Object Compiler (moc)
本文是一篇关于类class的帖子 the Meta-Object Compiler (moc) 元对象编译器是处理Qt的C++扩展的程序. moc工具读取C++头文件,如果它找到一个或者多个类声明包含 ...
- vue-auto-focus: 控制自动聚焦行为的 vue 指令
在网页的表单中,经常需要用程序来控制input和textarea的自动聚焦行为.例如我最近做的一个项目,有个装箱出库的流程,input框自动聚焦的流程如下:页面进入时自动聚焦到订单号输入框->订 ...
- ruby将mysql查询到的数据保存到excel
require "win32ole" require 'pathname' require 'mysql2' excel = WIN32OLE.new('excel.applica ...
- node.JS中配置http-server
http-server 是一个简单的HTTP服务器, 基于 nodeJs,在nodejs命令行中配置http服务器. 项目结构:
- qtCreator 快捷键
编号 快捷键 功能 1 Esc 切换到代码编辑状态 2 F1 查看帮助(选中某一类或函数,按下F1,出现帮助文档) 3 F2 在光标选中对象的声明和定义之间切换(和Ctrl+鼠标左键一样的效果,选中某 ...
- javascript 高级程序设计1--14章重点总结
js简介 首先介绍了js是一种专门与网页交互而设计的脚本语言.主要由ECMAScript 文档对象模型(DOM) 浏览器对象模型(BOM)三部分组成.分别用来提供核心语言,提供访问和操作网页内容的方法 ...
- 微信js-sdk调用
之前在做微信的时候,在微信支付还有调起微信扫一扫的时候,用过js-sdk.最近,被几个做前端的同学问到了具体的流程,想想,还是写下来好点. 微信js-sdk,是微信提供给网页开发设计者使用的, ...
- 使用log4cxx在GUI 程序中将信息输出到Console
之前看到有个方法是在项目属性设置里实现的 以VS2010为例: 右键Project选择Properties->Configuration Properties->Build Events- ...