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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5536759/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 18:23:24  来源:igfitidea点击:

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

c++cpthreadscondition-variable

提问by Asher Saban

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. I tried to test it and nothing happens. Is this can cause unexpected behavior or worse?

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

thank you!

谢谢你!

回答by stefaanv

The answer of blaze comes closest, but is not totally clear:
conditional variables should only be used to signal a change in a condition.

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

Thread 1 checks a condition. 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:

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

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. He doesn't care whether threads are waiting or not:

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

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
  • some bits in a bitset are set, so the waiting thread can handle the corresponding events
  • 队列不为空,因此可以从队列中取出一个条目
  • 设置了一个布尔标志,因此线程等待 s 直到另一个线程发出信号可以继续
  • bitset 中的一些位被设置,因此等待线程可以处理相应的事件

see also pthread example

另见pthread 示例

回答by sergico

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()*. 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. When thread A will reach the sync point, it will find the semaphore incremented and will enter the critical session.

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

回答by blaze

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. 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(): f.e., all readers may be just doing message processing when writer adds another data piece in queue.

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

回答by RobH

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.

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

回答by beroal

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. 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

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

The pthread_cond_signal()and pthread_cond_broadcast()functions have no effect if there are no threads currently blocked on cond.

如果当前没有线程阻塞在 上,pthread_cond_signal()pthread_cond_broadcast()函数将不起作用cond

So don't worry and be happy.

所以不要担心,要快乐。