27

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

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

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

谢谢你!

4

5 回答 5

39

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

线程 1 检查条件。如果条件不满足,他会等待条件变量,直到条件满足。因为首先检查条件,所以他不应该关心条件变量是否已发出信号:

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

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

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

底线是:通信是通过某种条件完成的。条件变量只唤醒等待线程,以便它们检查条件

条件示例:

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

另请参见pthread 示例

于 2011-04-04T12:28:53.333 回答
7

我的 2 美分:当没有线程被阻塞调用 *pthread_cond_wait()* 时,我不知道调用 *pthread_cond_signal()* 的副作用。这确实是一个实现细节我认为,如果您的线程/定时模型不能保证等待和信号之间的正确顺序,那么当您可以发出信号时,您可能应该考虑使用不同的同步机制[例如简单的信号量]来自线程 B 的信号量,即使线程 A 尚未到达同步点。当线程 A 到达同步点时,它会发现信号量增加并进入关键会话。

于 2011-04-04T09:58:32.130 回答
5

我写下我的答案是因为我看不到能让人们平静下来的答案。我还偶然发现了那个教程中关于“逻辑错误”的奇怪而令人不安的警告。请注意,关于pthread_cond_signal. 我确信这是对术语的不幸选择,或者是本教程作者的一个明显错误。他们的主张可能会被解释为进程将在这种情况下因错误而终止,或者任何允许这种情况的程序都是不正确的。没有什么是真的。这种情况很常见。文件说

如果当前没有阻塞在 上的线程,则pthread_cond_signal()andpthread_cond_broadcast()函数无效cond

所以不要担心,要快乐。

于 2019-12-07T08:11:19.317 回答
3

条件变量允许一个线程从等待中唤醒另一个线程。它们仅在您触发条件时有线程等待时才起作用。确保这种情况的方法是等待线程锁定与条件链接的互斥锁,并让信号线程在触发条件之前锁定该互斥锁。换句话说,如果另一个线程已锁定互斥锁但现在正在等待,则信号线程只能锁定互斥锁并触发条件。

我最熟悉 boost,所以我将在这个例子中使用它:

// 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();
}

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

于 2011-04-04T09:52:26.050 回答
3

如果您不关心此信号会丢失 - 没有错误。如果您期望稍后到来的等待线程立即从 cond_wait() 唤醒,这只是一个错误。

由于这是 pthread_cond 的常见用例,因此教程称之为逻辑错误。但是什么都不会崩溃,也不会发生意外的行为。在正常的执行流程中 cond_signal() 仍然可能在 cond_wait() 中没有线程时发出: fe,当 writer 在队列中添加另一个数据片段时,所有 reader 可能只是在进行消息处理。

于 2011-04-04T10:29:07.653 回答