使用pthread_cond_timedwait()超时时间设置问题

最近在使用pthread_cond_timedwait的时候,发现当超时时间设置成1秒以下的值时,返回结果提示函数参数设置错误。首先来看一下pthread_cond_timedwait的原型:

#include
int pthread_cond_timedwait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex,
const struct timespec *restrict abstime);

abstime是一个绝对时间,struct timespce的原型为:

struct timespec
{
__time_t tv_sec;        /* Seconds. */
long int tv_nsec;       /* Nanoseconds. */
};

其中tv_sec是秒,tv_nsec是纳秒(即1000,000,000分之一秒)

那么,看一下我之前出错的代码:

struct timespec abstime;
abstime.tv_nsec = (timeout_ms % 1000) * 1000000;
abstime.tv_sec = time(NULL) + timeout_ms / 1000;
pthread_cond_timedwait(&_read_cond, &_read_mutex, &abstime);

以上代码有问题,主要是因为time(NULL)的返回结果的精度是秒级的,那么如果当前时间是m秒+n毫秒,那么实际等待的时间只是timeout_ms – n,且还有可能发生n > timeout_ms的情况,这种情形下,如果这段代码处在一处while循环内,则会造成大量的pthread_cond_timedwait系统调用,并造成大量的context switch,系统CPU会占用很高。

正确的代码应该改为如下:

struct timespec abstime;
struct timeval now;
gettimeofday(&now, NULL);
int nsec = now.tv_usec * 1000 + (timeout_ms % 1000) * 1000000;
abstime.tv_nsec = nsec % 1000000000;
abstime.tv_sec = now.tv_sec + nsec / 1000000000 + timeout_ms / 1000;

pthread_cond_timedwait(&_read_cond, &_read_mutex, &abstime);

通过gettimeofday获得精确到微秒(1000,000分之一秒)的时间数据,并处理不足一秒加上超时时间超过一秒的情况(即tv_sec上需要加上nsec/1000000000)。

你可能感兴趣的:(Linux)