那么pthread_cond_timedwait()

时间:2009-09-28 12:47:13

标签: c pthreads

void wait(int timeInMs)
{
    struct timespec timeToWait;
    timeToWait.tv_sec = 5;
    timeToWait.tv_nsec = timeInMs*1000;

    int rt;

    pthread_mutex_lock(&fakeMutex);
    rt = pthread_cond_timedwait(&fakeCond, &fakeMutex, &timeToWait);
    pthread_mutex_unlock(&fakeMutex);
}

我正在使用此代码尝试让一个线程等待一下,但它根本不起作用。没有错误,它只是不会使程序执行得更慢。

我想也许每个线程都需要拥有它自己的条件和互斥量,但这对我来说真的没有意义。

7 个答案:

答案 0 :(得分:16)

使用任何睡眠变体,都无法保证行为。由于内核不知道不同的线程,所有线程也可以休眠。

使用更安全,更清洁的解决方案是pthread_cond_timedwait。您错误地使用了API。这是一个更好的例子:

pthread_mutex_t fakeMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t fakeCond = PTHREAD_COND_INITIALIZER;

void mywait(int timeInMs)
{
    struct timespec timeToWait;
    struct timeval now;
    int rt;

    gettimeofday(&now,NULL);


    timeToWait.tv_sec = now.tv_sec+5;
    timeToWait.tv_nsec = (now.tv_usec+1000UL*timeInMs)*1000UL;

    pthread_mutex_lock(&fakeMutex);
    rt = pthread_cond_timedwait(&fakeCond, &fakeMutex, &timeToWait);
    pthread_mutex_unlock(&fakeMutex);
    printf("\nDone\n");
}

void* fun(void* arg)
{
    printf("\nIn thread\n");
    mywait(1000);
}

int main()
{
    pthread_t thread;
    void *ret;

    pthread_create(&thread, NULL, fun, NULL);
    pthread_join(thread,&ret);
}

您需要指定从当前时间等待的时间。因为你只告诉5秒和几纳秒,它发现时间已经过去而且没有等待...如果有任何疑问,请告诉我。

答案 1 :(得分:13)

pthread_cond_timedwait函数需要绝对时间,而不是相对时间。您需要等待的时间,而不是等待的时间。

答案 2 :(得分:10)

pthread_cond_timedwait使用绝对时间,因此需要:

  • 使用gettimeofday检索当前时间。
  • timespec.tv_nsec是纳秒,它不能大于1秒。
  • timeval.tv_usec是微秒(1000纳秒)。
  • timeInMs是毫秒:1毫秒= 1000微秒= 1000 * 1000纳秒。

    void wait(int timeInMs)
    {
        struct timeval tv;
        struct timespec ts;
    
        gettimeofday(&tv, NULL);
        ts.tv_sec = time(NULL) + timeInMs / 1000;
        ts.tv_nsec = tv.tv_usec * 1000 + 1000 * 1000 * (timeInMs % 1000);
        ts.tv_sec += ts.tv_nsec / (1000 * 1000 * 1000);
        ts.tv_nsec %= (1000 * 1000 * 1000);
    
        n = pthread_cond_timedwait(&condition, &mutex, &ts);
        if (n == 0)
            // TODO: singaled
        else if (n == ETIMEDOUT)
            // TODO: Time out.
    }
    

答案 3 :(得分:3)

考虑到你正在使用timespec,你的目标不是同步而是等待我建议纳米睡眠。

#include <time.h>

.
.
.

  struct timespec remain;
  remain.tv_sec = 5;
  remain.tv_nsec = timeInMs * 1000;

  do {
    if ( nanosleep( &remain, &remain ) == 0 || errno != EINTR ) {
      break;
    }
  } while ( 1 );

.
.
.

答案 4 :(得分:2)

该代码无法休眠,它会检查条件一段时间。因为你可能没有设置cond ok它只是立即返回。

如果您不愿意在信号周围同步线程,那么pthread_cond _wait不是您需要的。检查here条件变量的工作原理。

如果你想用秒精确睡眠,请使用sleep

如果你想以微秒精度睡觉,请使用select时间长度。

答案 5 :(得分:1)

这是一个我从主循环创建线程的示例,它执行目录扫描并且超时为5秒。并且来自线程的信令使用全局的条件变量发生。我们一直在检查来自线程的信号:

    pthread_cond_t C_KISU_SwagntUtilityBase::m_cond; /*Global variable*/
/*Inside main function*/    
/*Local variables*/
          pthread_condattr_t l_attr;
          pthread_condattr_init(&l_attr);
          pthread_condattr_setclock(&l_attr, CLOCK_MONOTONIC);
          pthread_cond_init(&C_KISU_SwagntUtilityBase::m_cond, &l_attr);

          Int32 l_threadid = pthread_create(&l_updatethread,NULL,C_KISU_SwagntUtilityBase::ThreadScanDirectoryByFilter,&l_filer);
          if(CMP_ZERO == l_threadid)
          {
            pthread_mutex_t l_mutex = PTHREAD_MUTEX_INITIALIZER;
            struct timespec l_ts;
            if (clock_gettime(CLOCK_MONOTONIC, &l_ts) == INIT_NEGONE)
            {
             /* Handle error */
            }
            printf("\n Setting max time to  run ThreadScanDirectoryByFilter as 5 second"));
            l_ts.tv_sec += l_filer.m_max_scan_time;

            if(l_filer.m_scan_status == 0)
            {
              pthread_mutex_lock(&l_mutex);
              int l_rt = pthread_cond_timedwait(&C_KISU_SwagntUtilityBase::m_cond, &l_mutex, &l_ts);
              if (ETIMEDOUT == l_rt)
              {
                printf("\n timeout has happened before scan routine could finish"));
              }
              else if (EOK  == l_rt)
              {
                printf("\n Scan successful"));
              }
              else
              {
                printf("\n Unknown error while timeout condition check"));
              }
              pthread_mutex_unlock(&l_mutex);
            }
          }
          else
          {
            printf("\n Error while creating thread\n");

          }

答案 6 :(得分:0)

主要参考:http://pubs.opengroup.org/onlinepubs/009695299/functions/pthread_cond_timedwait.html

上面andrewrk的代码的修正

我可以确认Adrian May的gettimeofday不能正常运行! 像这样的无限线程内的andrewrk的代码行为

static void * thread_infinite(void * unused) {
while (1) {
        // compute stuff
        mywait(5);
}

是不可预测的:它运行大约700倍,直到阻塞!

andrewrk的正确代码版本是:

pthread_mutex_t fakeMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t fakeCond = PTHREAD_COND_INITIALIZER;

void mywait(int timeInS)
{
    struct timespec ts;
    struct timeval now;
    int rt = 0;

//    gettimeofday(&now,NULL); // DOES NOT FUNCTION CORRECTLY
//    timeToWait.tv_sec = now.tv_sec+5;
//    timeToWait.tv_nsec = (now.tv_usec+1000UL*timeInMs)*1000UL;

    clock_gettime(CLOCK_REALTIME, &ts);
    ts.tv_sec += timeInS;

    pthread_mutex_lock(&fakeMutex);

    do {
        rt = pthread_cond_timedwait(&fakeCond, &fakeMutex, &ts);
        }
    while (rt == 0);

    pthread_mutex_unlock(&fakeMutex);
}
相关问题