关于如何使用pthread_cond_timedwait()超时接口

来源:互联网 发布:淘宝账户被冻结一个月 编辑:程序博客网 时间:2024/05/16 18:24

之前大家讨论说pthread_cond_timedwait()接口不能用,如果需要超时返回功能的话必须写一个定时器来实现.但是该操作太昂贵了,其实可以直接使用该接口来实现超时等待功能的,下面描述我对该接口的了解及用法,仅供参考.

1.    POSIX提供了多种时钟类型,其中包括以下两种:
CLOCK_REALTIME: Systemwide realtime clock. 系统范围内的实时时钟,是个软件时钟,可以通过命令等方式修改该系统时间.
CLOCK_MONOTONIC:Represents monotonic time. Cannot be set. 表示单调时间,为系统起机时到现在的时间,不能被设置跟修改.

pthread_cond_timedwait()在没有设置条件变量属性的时候,默认用的是CLOCK_REALTIME软件时间,因此在极端情况下会出现实际等待的时间与设置的超时时间不同.
下面介绍下如何正确使用pthread_cond_timedwait()接口

2.    正确使用pthread_cond_timedwait()接口方式即将测量时间参照改为CLOCK_MONOTONIC,这个需要在初始化时设置条件变量的属性,之后再设置超时时间.例子如下:
    ret = pthread_condattr_init(&(pthread_info.condattr));
    if (ret != 0) {
        exit(1);
    }
ret = pthread_condattr_setclock(&(pthread_info.condattr), CLOCK_MONOTONIC);

ret = pthread_cond_init(&(pthread_info.cleanup_queue_wait), &(pthread_info.condattr));

struct timespec tv;
clock_gettime(CLOCK_MONOTONIC, &tv);
PTHREAD_TASK_DBG(LOGS_DEBUG, "now time:%d\n", tv.tv_sec);
tv.tv_sec += 30;-这里设置30秒后没收到事件超时返回
ret = pthread_cond_timedwait(&(pthread_info.cleanup_queue_wait), &(pthread_info.cleanup_queue_lock), &tv);


运行如下:


从上可以看出,使用该方式无论对系统时间设置为任何值时,系统运行时间都不会被修订,同时该线程也不会被触发返回,依旧是原先的30秒超时.

3.    其实使用CLOCK_REALTIME作为测量时间参照也是可行的,只是在极端的情况下(如在获取当前系统时间后系统时间马上被修订)时,这个超时时间就不正确了,不过这是小概率事件.
例子如下:
struct timespec tv;
tv.tv_sec = time(NULL);-极端情况下在获取当前系统时间后系统时间马上被修订
PTHREAD_TASK_DBG(LOGS_DEBUG, "now time:%d\n", tv.tv_sec);
tv.tv_sec += 30;-这里设置30秒后没收到事件超时返回
ret = pthread_cond_timedwait(&(pthread_info.cleanup_queue_wait), &(pthread_info.cleanup_queue_lock), &tv);

运行如下:
 


从上面可以看出,使用该方式在线程进入超时等待后,无论将系统时间改成以前后以后的时间,time(NULL)会返回当前设置后的时间,但线程都不会被触发返回.

4.    参考资料:
http://man.chinaunix.net/unix/susv3/functions/pthread_condattr_setclock.html
http://man.chinaunix.net/unix/susv3/functions/pthread_cond_timedwait.html

0 0