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

时间:2011-04-04 09:35:46

标签: c++ c pthreads condition-variable

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

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

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

谢谢你!

5 个答案:

答案 0 :(得分:35)

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

线程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 example

答案 1 :(得分:5)

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

答案 2 :(得分: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();
}

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

答案 3 :(得分:3)

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

由于这是pthread_cond的常用用例,因此tutorial会调用此逻辑错误。但没有任何事情会崩溃,也不会发生意外行为。在正常执行流程中,cond_signal()仍然可以在cond_wait()中没有线程时发出:f.e。,当writer在队列中添加另一个数据时,所有读者可能正在进行消息处理。

答案 4 :(得分:0)

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

  

pthread_cond_signal()pthread_cond_broadcast()函数具有   如果cond上当前没有线程被阻塞,则无效。

所以不要担心,要开心。