C - pthread条件变量

时间:2017-10-12 10:39:17

标签: c multithreading condition-variable

所以我有这个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情况下等待。非常欢迎所有提示,谢谢。

1 个答案:

答案 0 :(得分:2)

请记住,条件变量只是表明封闭程序中的某些条件已发生变化。使用条件变量时最重要的是要了解条件是什么并确保它正确建模。该条件通常也称为谓词

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

  • 其他一些线程推送工作在堆栈上。在这种情况下,您希望您的线程被唤醒以帮助完成新推动的工作。
  • 所有线程都已进入等待状态。在这种情况下,没有剩下的工作了,因为所有线程都已完成,所以不会再将任何工作推送到堆栈。

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

第一个条件已在程序中建模,因为您只需检查堆栈以查明是否有任何新工作可用。然而,第二个条件不是。您无法检查当前处于等待状态的线程数。

解决方案是对该条件进行建模,这可以通过引入计数器轻松完成:

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返回后我们会检查封闭条件以确定下一步该做什么。