C - pthread 条件变量

C - pthread condition variables

所以我有这个 while 循环,它可以处理多个线程,我希望只要所有线程都在工作,它就可以工作,比如:

while(*threads are working*) {
 pthread_mutex_lock 
 if(stack is not empty) {
     pthread_cond_broadcast
     *critical work*
     pthread_mutex_unlock
 }
 else {
     pthread_cond_wait
     pthread_mutex_unlock
 }

我基本上希望这个 while 循环 运行 直到所有线程都检查了堆栈是否为空并且在 else 情况下等待。非常欢迎所有提示,谢谢。

请记住,条件变量只是表示封闭程序中的某些条件已更改。使用条件变量时最重要的事情是了解该条件是什么并确保它被正确建模。该条件通常也称为 predicate.

在您的情况下,您的线程同时充当共享堆栈上工作的生产者和消费者。如果一个线程用完了工作,它将进入等待状态,只有在满足以下条件之一时才会 return:

  • 其他一些线程将工作推入堆栈。在这种情况下,您希望唤醒您的线程以帮助完成新推送的工作。
  • 所有线程都进入了等待状态。在那种情况下,没有更多的工作剩余,并且由于所有线程都已完成,因此不会再将任何工作推入堆栈。

这两个条件的分离构成您的谓词。

第一个条件已经在程序中建模,因为您可以简单地检查堆栈以找出是否有任何新工作可用。然而第二个条件不是。您无法检查当前有多少线程处于等待状态。

解决方案是也对该条件进行建模,这很容易通过引入计数器来完成:

int threads_waiting = 0;
while(true) {
  pthread_mutex_lock 
  if(stack is not empty) {
    *critical work*
    if(i_pushed_some_work_on_the_stack) {
      pthread_cond_broadcast   // wake up any threads that have gone to sleep
                               // because the stack ran out of work
    }
    pthread_mutex_unlock
  } else {
    ++threads_sleeping
    if(threads_sleeping == number_of_threads) {
      pthread_cond_broadcast     // wake up any threads waiting for
                                 // the last thread to finish                  
      pthread_mutex_unlock       // ... and we're done!
      return
    }
    while(true) {
      pthread_cond_wait
      if(stack is not empty) {
        // there is more work available; continue outer loop
        --threads_sleeping
        break;
      } else if(threads_sleeping == number_of_threads) {
        // everybody is done, so let's return
        pthread_mutex_unlock
        return
      } else {
        // spurious wakeup; go back to sleep
      }
    }
    pthread_mutex_unlock
}

请注意我们如何在谓词发生变化时调用 pthread_cond_broadcast,并且在从 pthread_cond_wait 调用 return 之后,我们检查封闭条件以确定下一步要做什么。