简体   繁体   English

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

[英]condition variable - why calling pthread_cond_signal() before calling pthread_cond_wait() is a logical error?

It's written in POSIX threads tutorial https://computing.llnl.gov/tutorials/pthreads/ that it is a logical error.它写在 POSIX 线程教程https://computing.llnl.gov/tutorials/pthreads/ 中,这是一个逻辑错误。

my question is why it is a logical error?我的问题是为什么这是一个逻辑错误?

In my program i need to use these signals, however i cannot guarantee that there will be a thread that will be in _cond_wait state.在我的程序中,我需要使用这些信号,但是我不能保证会有一个处于 _cond_wait 状态的线程。 I tried to test it and nothing happens.我试图测试它,但没有任何反应。 Is this can cause unexpected behavior or worse?这会导致意外行为或更糟吗?

thank you!谢谢你!

The answer of blaze comes closest, but is not totally clear: blaze 的答案最接近,但并不完全清楚:
conditional variables should only be used to signal a change in a condition .条件变量应该只用于表示条件的变化

Thread 1 checks a condition.线程 1 检查条件。 If the condition doesn't meet, he waits on the condition variable until the condition meets.如果条件不满足,他就等待条件变量,直到条件满足。 Because the condition is checked first, he shouldn't care whether the condition variable was signaled:因为先检查条件,所以他不应该关心条件变量是否发出信号:

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

Thread 2 changes the condition and signals the change via the condition variable.线程 2 更改条件并通过条件变量发出更改信号。 He doesn't care whether threads are waiting or not:他不在乎线程是否在等待:

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

The bottom line is: the communication is done via some condition.底线是:通信是通过某种条件完成的。 A condition variable only wakes up waiting threads so they can check the condition .条件变量只唤醒等待线程,以便它们可以检查条件

Examples for conditions:条件示例:

  • Queue is not empty, so an entry can be taken from the queue队列不为空,因此可以从队列中取出一个条目
  • A boolean flag is set, so the thread wait s until the other thread signal it's okay to continue设置了一个布尔标志,因此线程等待 s 直到另一个线程发出信号可以继续
  • some bits in a bitset are set, so the waiting thread can handle the corresponding events bitset 中的一些位被设置,因此等待线程可以处理相应的事件

see also pthread example另见pthread 示例

My 2 cents: I do not know the side effects of calling *pthread_cond_signal()* when no thread has been blocked calling *pthread_cond_wait()*.我的 2 美分:当没有线程被阻塞调用 *pthread_cond_wait()* 时,我不知道调用 *pthread_cond_signal()* 的副作用。 This is really an implementation detail What I think is that, if your threading/timimg model do not guarantee the rigth order between wait and signal, probably you should consider a different sync mechanism [like a simple semaphore , for example] when you can signal the semaphore from thread B even if the thread A has nor reached the sync point.这真的是一个实现细节我认为,如果您的线程/timimg 模型不能保证等待和信号之间的正确顺序,那么您可能应该考虑使用不同的同步机制 [例如简单的信号量],当您可以发出信号时来自线程 B 的信号量,即使线程 A 还没有到达同步点。 When thread A will reach the sync point, it will find the semaphore incremented and will enter the critical session.当线程 A 将到达同步点时,它会发现信号量增加并进入关键会话。

I write my answer because I do not see the one that will calm people.我写我的答案是因为我没有看到能让人们平静的答案。 I also stumbled upon that bizarre disturbing warning about “logical error” in that tutorial.我还在那个教程中偶然发现了关于“逻辑错误”的奇怪的令人不安的警告。 Note that there is nothing about this “error” in the POSIX documentation article on pthread_cond_signal .请注意, 关于pthread_cond_signal的 POSIX 文档文章中没有关于此“错误”的任何内容。 I am sure that this is an unfortunate choice of the term or a plain mistake on part of the author of the tutorial.我确信这是一个不幸的术语选择,或者是教程作者的一个明显错误。 Their claim may be interpreted as if a process will terminate with an error in this situation or that any program permitting this situation is incorrect.他们的声明可能被解释为在这种情况下进程将因错误而终止,或者任何允许这种情况的程序都是不正确的。 Nothing of the sort is true.没有什么是真的。 Such situations are common.这种情况很常见。 The documentation says that文档说

The pthread_cond_signal() and pthread_cond_broadcast() functions have no effect if there are no threads currently blocked on cond .如果当前没有线程阻塞在cond上,则pthread_cond_signal()pthread_cond_broadcast()函数无效。

So don't worry and be happy.所以不要担心,要快乐。

A condition variable allows one thread to wake another up from a wait.条件变量允许一个线程从等待中唤醒另一个线程。 They work only if there is a thread waiting at the moment when you trigger the condition.只有当您触发条件时有线程在等待时,它们才起作用。 The way to ensure that this is the case is for the waiting thread to lock a mutex which is linked to the condition, and for the signalling thread to lock that mutex before triggering the condition.确保这种情况的方法是等待线程锁定链接到条件的互斥锁,并且信号线程在触发条件之前锁定该互斥锁。 In other words, the signalling thread can only lock the mutex and trigger the condition if the other thread had the mutex locked but is now waiting.换句话说,如果另一个线程锁定了互斥锁但现在正在等待,则信号线程只能锁定互斥锁并触发条件。

I'm most familiar with boost, so I'll use that in this example:我最熟悉 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();
}

To signal a condition variable when there is no corresponding wait is a logical error because nothing will ever receive the signal.在没有相应的等待时向条件变量发出信号是一个逻辑错误,因为没有任何东西会收到信号。 Condition variables don't remain in a signalled state.条件变量不会保持在有信号的状态。

If you do not care that this signal will be lost - there is no error.如果你不关心这个信号会丢失 - 没有错误。 It is only an error if you expect later coming waiting thread to wake from cond_wait() immediately.如果您希望稍后等待的线程立即从 cond_wait() 唤醒,这只是一个错误。

Since this is usual use case for pthread_cond, tutorial calls this logical error.由于这是 pthread_cond 的常见用例,因此教程称此为逻辑错误。 But nothing will crash and no unexpected behavior will occur.但是什么都不会崩溃,也不会发生意外行为。 In normal execution flow cond_signal() still may be issued when there is no threads in cond_wait(): fe, all readers may be just doing message processing when writer adds another data piece in queue.在正常的执行流程中,当cond_wait()中没有线程时,仍然可能会发出cond_signal():fe,当写入器向队列中添加另一个数据时,所有读取器可能只是在进行消息处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM