pthread_cond_timedwait立即返回

时间:2009-03-19 03:00:46

标签: c multithreading conditional system pthreads

我遇到了一个奇怪的问题。我有以下代码:

    dbg("condwait: timeout = %d, %d\n", 
        abs_timeout->tv_sec, abs_timeout->tv_nsec);
    ret = pthread_cond_timedwait( &q->q_cond, &q->q_mtx, abs_timeout );
    if (ret == ETIMEDOUT)
    {
      dbg("cond timed out\n");
      return -ETIMEDOUT;
    }

dbg在每一行之前调用gettimeofday,并在行前加上时间。它产生以下输出:

    7.991151: condwait: timeout = 5, 705032704
    7.991158: cond timed out

如您所见,两条调试行之间仅传递了7微秒,但pthread_cond_timedwait返回ETIMEDOUT。怎么会发生这种情况?我甚至尝试在初始化cond变量时将时钟设置为其他内容:

int ret;
ret = pthread_condattr_init(&attributes);
if (ret != 0) printf("CONDATTR INIT FAILED: %d\n", ret);
ret = pthread_condattr_setclock(&attributes, CLOCK_REALTIME);
if (ret != 0) printf("SETCLOCK FAILED: %d\n", ret);
ret = pthread_cond_init( &q->q_cond, &attributes );
if (ret != 0) printf("COND INIT FAILED: %d\n", ret);

(没有打印出任何错误消息)。我尝试了CLOCK_REALTIMECLOCK_MONOTONIC

此代码是阻塞队列的一部分。我需要这样的功能,如果在5秒内没有任何东西放在这个队列上,就会发生其他事情。互斥锁和cond都被初始化,因为如果我不使用pthread_cond_timedwait,阻塞队列就可以正常工作。

4 个答案:

答案 0 :(得分:14)

pthread_cond_timedwait需要绝对时间,而不是相对时间。您需要通过将当前时间添加到超时值来使您的等待时间绝对。

答案 1 :(得分:8)

timespec的溢出通常是奇怪超时的罪魁祸首 检查 EINVAL:

void timespec_add(struct timespec* a, struct timespec* b, struct timespec* out)
{
    time_t sec = a->tv_sec + b->tv_sec;
    long nsec = a->tv_nsec + b->tv_nsec;

    sec += nsec / 1000000000L;
    nsec = nsec % 1000000000L;

    out->tv_sec = sec;
    out->tv_nsec = nsec;
}

答案 2 :(得分:3)

条件变量可以虚假地解除阻塞。您需要在循环中检查它并每次检查条件。您可能还需要更新超时值。

我找到了pthread_cond_timedwait here的一些文档。

  

在那里使用条件变量时   始终是布尔谓词   涉及共享变量   每个条件等待都是真的   如果线程应该继续。伪   从中醒来   pthread_cond_timedwait()或   pthread_cond_wait()函数可以   发生。自从归来   pthread_cond_timedwait()或   pthread_cond_wait()并不意味着   关于这个价值的任何事情   谓词,谓词应该是   在返回时重新评估。

答案 3 :(得分:0)

正如提到的其他答案中一样,你必须使用绝对时间。自C11起,您可以使用timespec_get()

struct timespec time;
timespec_get(&time, TIME_UTC);
time.tv_sec += 5;

pthread_cond_timedwait(&cond, &mutex, &time);