【问题标题】:pthread_cond_timedwait returning immediatelypthread_cond_timedwait 立即返回
【发布时间】:2010-10-14 05:44:39
【问题描述】:

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

    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 秒内没有任何东西放在这个队列上,就会发生其他事情。 mutex 和 cond 都已初始化,因为如果我不使用 pthread_cond_timedwait,阻塞队列可以正常工作。

【问题讨论】:

    标签: c multithreading conditional system pthreads


    【解决方案1】:

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

    【讨论】:

    • 哦,明白了。您可以使用 pthread_get_expiration_np() 来计算 abs 时间。
    • @Claudiu pthread_get_expiration_np() 在我的 GNU/Linux 上不可用。相反,我不得不:timeval now; gettimeofday(&now, NULL); long int abstime_ns_large = now.tv_usec*1000 + delay_ns; timespec abstime = { now.tv_sec + (abstime_ns_large / 1000000000), abstime_ns_large % 1000000000 }; 其中 delay_ns 是所需的延迟(以纳秒为单位)。然后在您的 pthread_cond_timedwait 调用中使用 abstime。
    【解决方案2】:

    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;
    }
    

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        【解决方案4】:

        正如在其他答案中已经提到的,您必须使用绝对时间。从 C11 开始,您可以使用 timespec_get()

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

        【讨论】:

          猜你喜欢
          • 2018-02-11
          • 2012-07-30
          • 1970-01-01
          • 2011-10-16
          • 2016-03-10
          • 2014-03-19
          • 2017-05-14
          • 2017-12-11
          • 1970-01-01
          相关资源
          最近更新 更多