【问题标题】:Pthread condition wait and signalPthread条件等待和信号
【发布时间】:2012-10-26 12:59:54
【问题描述】:

我对 pthread_cond_wait 和 pthread_cond_signal 函数有疑问。在阅读手册页后我也无法理解。

请考虑以下代码。

void* thread_handler(){
... // counts till COUNT_LIMIT is reached
if (count == COUNT_LIMIT) {
  pthread_cond_signal(&count_threshold_cv);
  printf("inc_count(): thread %ld, count = %d  Threshold reached.\n",
         my_id, count);
}
printf("inc_count(): thread %ld, count = %d, unlocking mutex\n",
       my_id, count);
...
}

void* thread_handler1(){
... // waits till the previous thread has finished counting
pthread_mutex_lock(&count_mutex);
while (count<COUNT_LIMIT) {
   pthread_cond_wait(&count_threshold_cv, &count_mutex);
   printf("watch_count(): thread %ld Condition signal received.\n", my_id);
}
pthread_mutex_unlock(&count_mutex);
pthread_exit(NULL);
}

代码按预期运行。我正在尝试理解代码。这是程序的工作原理

  1. 输入 thread_handler1 并执行 cond_wait。从手册页我了解到 cond_wait 将立即以原子方式释放锁。 那么为什么他们在thread_handler1下面又释放了锁

  2. 在第一个线程满足条件并达到条件信号后我希望阻塞的线程执行其步骤。相反,我在执行 cond_signal 的线程下面得到了 printfs。为什么会发生这种情况

  3. 总的来说,为什么我们需要在等待和发出信号之前获取锁。没有锁就不能这样做。

有关该程序的简要介绍,请在此处查看Complete program。您可以在“使用条件变量”部分找到它

提前致谢

奇丹巴拉姆

【问题讨论】:

  • 请注意,每当您修改 count 时,都应锁定互斥锁,并且通常应保持直到调用 pthread_cond_signal。 IE。顺序是:锁定、修改、信号(如果“准备好”)、解锁。
  • @WilliamMorris:如果您不需要在发出信号之前阻止新的服务员到达,您将通过在调用 pthread_cond_signal 之前解锁互斥锁来获得更好的性能(更少的上下文切换和/或更少往返内核空间)。
  • @R..:无论其他线程上的活动性质如何,保持互斥锁始终处于锁定状态。仅当这些信号事件非常频繁地发生时,性能才是一个问题。您提出的性能问题是否与实现尝试唤醒服务员的确切时间有关?如果它试图在信号传递后立即唤醒,那么显然它不能(因为信号器仍然有互斥锁) - 这可能会对性能产生轻微影响。但是如果实现等到互斥锁被释放,那么性能有什么区别吗?
  • 在 Linux 上,互斥锁锁定时发出信号不会唤醒服务员,而是使用特殊的 futex 命令将服务员重新排入互斥锁而不是条件变量。但是,当您随后解锁互斥锁以唤醒服务员时,这需要第二次系统调用,即到内核空间的额外往返。如果互斥体已经解锁,那么信号可以直接唤醒等待者,只需要往返内核空间一次。
  • 在没有像 Linux 这样的“requeue”命令的实现上,差异应该更加严重:服务员实际上会被唤醒,然后立即再次阻塞互斥体。我没有测量任何一种实现类型的性能差异,但假设(这通常是正确的)花费的时间主要由系统调用支配,只使用一个系统调用而不是两个应该是可衡量的性能提升。

标签: c linux multithreading pthreads


【解决方案1】:

输入 thread_handler1 并执行 cond_wait。从我理解的手册页 cond_wait 将立即以原子方式释放锁。那么为什么是 他们在thread_handler1下面再次释放锁

因为应该等待的线程会在调用wait 时释放锁,但在收到信号后会重新获取(当它可用时)。这就是为什么您需要稍后明确地重新发布它。

在第一个线程满足条件并命中条件后 信号我希望阻塞的线程执行它的步骤。 相反,我得到了执行线程下面的 printfs cond_signal。为什么会这样

因为调用signal 不会从CPU 切换线程。它将继续正常运行。

【讨论】:

  • 至于2),还要注意调用pthread_signal 不会释放你之前获得的锁。因此等待线程不能重新开始处理,直到信令线程调用pthread_unlock
  • 非常感谢您的回复。您能否解释一下为什么线程必须稍后执行显式 pthread_unlock 。我无法掌握答案。
  • @CHID:你是说问题1吗?
  • 是的都铎王朝。 Because the thread that is supposed to wait will release the lock when calling wait, but will then reacquire it when it gets signaled. That's why you need to rerelease it explicitly later. 具体来说,没有pthread_lock。并且被阻塞的线程“不需要立即安排”,因为发出信号的线程将执行自己的任务。这不会产生竞争条件吗?
  • @CHID:线程等待并释放锁。但是在收到继续执行的信号后,在重新获得锁之前不允许继续执行。因此,一旦锁再次可用,它将重新获得它,继续执行,但在完成后需要释放它。
猜你喜欢
  • 2018-02-07
  • 2012-04-12
  • 2016-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-04
相关资源
最近更新 更多