pthread_cond_timedwait的使用及疑问
来源:互联网 发布:四柱算命软件 编辑:程序博客网 时间:2024/05/21 17:50
条件变量是一种在并发编程中常用的同步原语。是一种通知机制,一个线程需要某种条件成立后,才能继续执行,如果条件不成立则阻塞等待条件成立,是wait端;另外的线程则是执行某些操作后,使条件成立,然后唤醒等待线程,是signal/broadcast端。
wait端的使用方式:
- 由于条件会被wait线程读取,被signal/broadcast线程修改,即写入。为了防止出现竞争,需要和mutex一起使用,使用mutex来保护条件。
- 在mutex已经锁住的情况下,才能调用wait。
- 由于spurious wakeup(虚假唤醒)的原因,wait函数返回并不代表条件已经成立,在wait函数返回后,需要再次判断条件是否成立。因此需要将wai调用放到while循环中。
wait端检测到条件不成立时,可以调用以下两个函数进行等待。
1 int pthread_cond_timedwait(pthread_cond_t *restrict cond,2 pthread_mutex_t *restrict mutex,3 const struct timespec *restrict abstime);4 int pthread_cond_wait(pthread_cond_t *restrict cond,5 pthread_mutex_t *restrict mutex);
这两个函数的区别是,第一个函数可以设置超时时间。这里主要说明第一函数的使用方法和我遇到的问题。timespec指定的是超时时刻的绝对时间,而不是相对时间,因此需要先获取当前时间,然后加上需要等待的时间才能得到用于设置的时间,当前时间通过gettimeofday获取。为简化操作,这里把这些操作封装为一个函数,用于设置以毫秒为单位的相对超时时间。我第一次写的获取绝对时间的函数如下:
1 void get_abstime_wait(int microseconds, struct timespec *abstime) 2 { 3 struct timeval tv; 4 int absmsec; 5 gettimeofday(&tv, NULL); 6 absmsec = tv.tv_sec * 1000 + tv.tv_usec / 1000; 7 absmsec += microseconds; 8 9 abstime->tv_sec = absmsec / 1000;10 abstime->tv_nsec = absmsec % 1000 * 1000000;11 }
第一个参数指定超时的相对时间,比如传500,表示500毫秒后超时。但是这样写几乎肯定使wait端线程进入busy loop状态。因为这些计算的中间结果,超出了int类型的表示范围,溢出了。添加打印后会发现abstime->tv_sec是一个很小的值,因此调用pthread_cond_timedwait后,立即就超时返回了。因此正确的写法是使用long long来保存结果,long long 类型在linux上是64位的,因此肯定不会溢出。
1 void get_abstime_wait(int microseconds, struct timespec *abstime) 2 { 3 struct timeval tv; 4 long long absmsec; 5 gettimeofday(&tv, NULL); 6 absmsec = tv.tv_sec * 1000ll + tv.tv_usec / 1000ll; 7 absmsec += microseconds; 8 9 abstime->tv_sec = absmsec / 1000ll;10 abstime->tv_nsec = absmsec % 1000ll * 1000000ll;11 }
使用pthread_cond_timedwait过程中遇到的另一个奇葩问题是,当时间被设置为1970年以前时,超时机制也会出问题。我的工作是搞嵌入式开发,遇到过一台设备的时钟芯片坏掉后,获取出来的时间有问题,导致时间被设置成了1970年以前,这竟然导致pthread_cond_timedwait长眠不醒。本来打算在ubuntu上重现一下,结果系统不让设置1970年以前的时间了,也许已经不支持1970年以前的时间了吧,就先不管了。如果那位大神知道怎么回事,麻烦通知小弟一声,小弟不甚感激。
- pthread_cond_timedwait的使用及疑问
- pthread_cond_timedwait及Linux下与时间有关的结构体
- pthread_cond_wait/pthread_cond_timedwait使用注意
- pthread_cond_timedwait
- pthread_cond_timedwait()
- pthread_cond_timedwait
- pthread_cond_timedwait
- Sharepoint 2007: 用户和权限的使用及疑问
- dll使用全局变量的疑问
- 使用VS2008的几个疑问
- 使用桥梁网的疑问
- 关于如何使用pthread_cond_timedwait()超时接口
- 关于如何使用pthread_cond_timedwait()超时接口
- 关于如何使用pthread_cond_timedwait()超时接口
- 使用pthread_cond_timedwait()超时时间设置问题
- C/C++ pthread_cond_timedwait()函数使用心得
- [Android] 使用ActionBar的Up导航的简介及一个疑问
- 关于面向对象及分层的疑问?
- window.name实现的跨域数据传输
- Unity移动开发热更新问题
- 1059. Prime Factors (25)--taste
- JavaScript window.location对象
- 【BestCoder】 HDOJ 5170 GTY's math problem
- pthread_cond_timedwait的使用及疑问
- JavaScript window.location对象
- 菜鸟的Linux学习笔记之命令find
- 【BestCoder】 HDOJ 5171 GTY's birthday gift
- 字符数组,指针与数组,动态数组
- LeetCode OJ 之 Maximal Rectangle (最大的矩形)
- LINQ 流程简介
- 自定义ViewFlipper 实现滚动效果
- Maven 报错: Failure to transfer classworlds:classworlds:pom:1.1-alpha-2 from