1. 程式人生 > >使用pthread_cond_timedwait()超時時間設定問題

使用pthread_cond_timedwait()超時時間設定問題

最近在使用pthread_cond_timedwait的時候,發現當超時時間設定成1秒以下的值時,返回結果提示函式引數設定錯誤。首先來看一下pthread_cond_timedwait的原型:

#include <pthread.h>
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)。