条件variables – 为什么在调用pthread_cond_wait()之前调用pthread_cond_signal()是一个逻辑错误?

这是写在POSIX线程教程https://computing.llnl.gov/tutorials/pthreads/这是一个逻辑错误。

我的问题是为什么这是一个逻辑错误?

在我的程序中,我需要使用这些信号,但是我不能保证会有一个线程处于_cond_wait状态。 我试图testing它,没有任何反应。 这是否会导致意外的行为或更糟?

谢谢!

火焰的答案最接近,但并不完全清楚:
条件variables只能用于表示条件的变化

线程1检查一个条件。 如果条件不符合,他等待条件variables,直到条件满足。 因为首先检查条件,所以他不应该关心条件variables是否被发信号:

pthread_mutex_lock(&mutex); while (!condition) pthread_cond_wait(&cond, &mutex); pthread_mutex_unlock(&mutex); 

线程2更改条件并通过条件variables发信号通知。 他不在乎线程是否在等待:

 pthread_mutex_lock(&mutex); changeCondition(); pthread_mutex_unlock(&mutex); pthread_cond_signal(&cond) 

底线是: 沟通是通过一些条件来完成的。 一个条件variables只唤醒等待线程,以便他们可以检查条件

条件示例:

  • 队列不是空的,所以成员可以从队列中取出
  • 一个布尔标志被设置,所以线程等待直到另一个线程信号继续
  • bitset中的一些位被设置,所以等待的线程可以处理相应的事件

另请参阅pthread示例

我的2美分:我不知道调用* pthread_cond_signal()*时,没有线程被阻止调用* pthread_cond_wait()*的副作用。 这实际上是一个实现细节我认为,如果你的线程/时序模型不能保证等待和信号之间的顺序,可能你应该考虑一个不同的同步机制(比如简单的信号量)即使线程A已经到达同步点也不能从线程B发出信号量。 当线程A到达同步点时,它会发现信号量递增,并进入关键会话。

条件variables允许一个线程从等待中唤醒另一个线程。 只有当你触发条件的时候有一个线程在等待的时候,它们才能工作。 确保这种情况的方法是等待线程locking与条件链接的互斥锁,并且在触发条件之前让信号线程locking该互斥锁。 换句话说,信号线程只能locking互斥体,并在其他线程locking互斥体但正在等待的情况下触发条件。

我最熟悉的提升,所以我会用在这个例子中:

 // A shared mutex, global in this case. boost::mutex myMutex; // Condition variable boost::condition_variable myCondition; void threadProc() { // Lock the mutex while the thread is running. boost::mutex::scoped_lock guard( myMutex ); while( true ) { // Do stuff, then... myCondition.wait( guard ); // Unlocks the mutex and waits for a notification. } } void func() { // Function wants to trigger the other thread. Locks the mutex... boost::mutex::scoped_lock guard( myMutex ); // Since the mutex is locked, we know that the other thread is // waiting on the condition variable... myCondition.notify_all(); } 

当没有相应的等待时发信号给一个条件variables是一个逻辑错误,因为什么都不会收到信号。 条件variables不会保持信号状态。

如果你不在意这个信号会丢失 – 没有错误。 如果您期望稍后等待线程立即从cond_wait()中唤醒,那只是一个错误。

由于这是pthread_cond的常见用例,因此tutorial会调用这个逻辑错误。 但是没有什么会崩溃,并且不会发生意外的行为。 在正常的执行stream程中cond_signal()仍然可以在cond_wait():fe中没有线程时发出,所以读写器在队列中添加另一个数据片段时可能正在做消息处理。