如何停止并继续pthread?

时间:2011-01-25 14:56:33

标签: c multithreading pthreads

我在C编码(实际上是在OOC中,然后编译为C)。

如何指示线程在特定检查点等待,直到某个其他线程告诉它继续?

我实际上在线程中使用了一个紧密的循环并且轮询我正在从主线程中更改的变量,但我认为这不是很好的表现,对吧?除此之外,当我在一个线程中进行紧密循环时,我是否应该在循环中包含一个睡眠以避免消耗大量的CPU功率而只是循环?

4 个答案:

答案 0 :(得分:12)

您似乎正在寻找pthread_cond_wait及其相关功能。

以下是manpage的引用示例:

  

考虑两个由互斥量mut保护的共享变量x和y,以及每当x变得大于y时要发信号的条件变量cond。

          int x,y;
          pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
          pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
     

等待直到x大于y,执行如下:

          pthread_mutex_lock(&mut);
          while (x <= y) {
                  pthread_cond_wait(&cond, &mut);
          }
          /* operate on x and y */
          pthread_mutex_unlock(&mut);
     

x和y的修改可能导致x变得大于y,如果需要,应该发出信号:

          pthread_mutex_lock(&mut);
          /* modify x and y */
          if (x > y) pthread_cond_broadcast(&cond);
          pthread_mutex_unlock(&mut);

最后它会满足您的要求:调用pthread_cond_wait(&cond)的线程被阻塞,直到另一个线程(例如您的主线程)调用pthread_cond_broadcast(&cond)。在此期间,它只处于blocked状态,并且不消耗CPU周期。

答案 1 :(得分:2)

我认为这是一个很好的候选人。线程应该等待一个条件,另一个线程应该发出信号,让这个线程继续。

你可以查找pthread_cond_init,这应该导致其他功能

答案 2 :(得分:2)

您应该查看正确的同步原语,例如互斥锁,条件变量和信号量。在这种情况下,听起来像condition variable是pthreads库中最合适的工具。

答案 3 :(得分:1)

只是让你知道发生了什么,“紧密循环”会消耗线程的CPU分配,就像线程执行的任何其他代码一样。唯一的区别是它什么都没做。好吧,我觉得让核心变得温暖......你可能永远都不想这样做,除非你关心上下文切换的成本,你知道肯定等待时间会很长比你的线程的时间片短,大约是1ms。我不知道睡眠是否和yield一样糟糕(AFAIK yield将你的线程设置为在你的优先级激活的线程列表的后面),但两者都至少会导致上下文切换的惩罚。上下文切换需要付出代价。上下文切换是当线程的时间片结束时发生的事情。它可以结束,因为你以收益或睡眠结束它,或者如果内核通过预先占用你来结束它。阅读有关SMP和自旋锁的信息,以了解有关上下文切换的更多信息以及紧密循环适用时的情况。

此外,当你睡觉时,你并不知道什么时候会再次醒来。所以你可能不想睡觉的一个原因是你需要快速完成任务。你可以等几个小时再重新安排。

其他人都为您提供了pthread_cond_wait解决方案,该解决方案需要通过互斥锁进行锁定,看起来简单明了。性能可能足以满足您的需求,但与使用信号(sigwait and pthread_kill)的解决方案相比相对较慢。复杂性会偷偷摸摸。

这里没有讨论为什么你在测试之前锁定一个互斥锁,如果你需要等待条件。原因是像这样的代码有一个缺陷:

      while (x <= y) {
              pthread_cond_wait(&cond, &mut);
      }

你的线程可以测试(X&lt; = Y),看它必须等待,但是在它自己附加到条件值之前要预先设定。刚修改x或y的其他一些线程在第一个线程附加到条件之前在该时间片中发出信号。以这种方式,状态信号丢失。所以最终发生的是你修改变量信号的变量,你必须添加锁。

      pthread_mutex_lock(&mut);
      /* modify x and y */
      if (x > y) pthread_cond_broadcast(&cond);
      pthread_mutex_unlock(&mut);

这可能意味着您在许多不同的地方添加这些互斥锁,因此您的代码会变得更复杂和更慢。挂起线程等待条件的可能性总是存在的。循环,测试,睡眠解决方案没有这些问题。因此,如果已知等待时间很短,则在循环中使用睡眠可能是一个很好的解决方案。特别是如果你可以在测试之间睡一会儿或更长时间。如果可以,那么不要打扰互斥和条件。如果睡眠时间很短,比如1ms而且等待时间很长,比如几分钟或几小时,那么你最终会因为不断醒来并重新入睡而浪费一些资源。你必须判断。

还要注意,有时内核会尝试立即唤醒服务员线程,有时会出现延迟。如果线程太快唤醒,它将在互斥锁被锁定时唤醒并立即返回睡眠状态,直到互斥锁解锁。如果这成为一个问题,请以这种方式发出信号:

pthread_mutex_lock(&mut);
/* modify x and y */
if (x > y) {
    pthread_mutex_unlock(&mut);
    pthread_cond_broadcast(&cond);
} else
    pthread_mutex_unlock(&mut);

感谢user576875,我复制的代码示例。