如果被虚假唤醒,消费者线程是不是会收到 condition_variable 通知信号
Posted
技术标签:
【中文标题】如果被虚假唤醒,消费者线程是不是会收到 condition_variable 通知信号【英文标题】:Will consumer thread receive condition_variable notify signal if spuriously woken up如果被虚假唤醒,消费者线程是否会收到 condition_variable 通知信号 【发布时间】:2017-05-13 14:40:01 【问题描述】:我们知道条件变量容易被虚假唤醒。假设我们有一个与互斥锁和条件变量同步的 1-producer-1-consumer 队列。消费者线程被虚假唤醒。 问题是——消费者线程会错过来自生产者的通知信号吗? 我知道这是极不可能的.. 但是通过这种实现是否仍然有可能丢失队列中的最后一个元素?
【问题讨论】:
"消费者线程会错过生产者的通知信号吗?" 为什么会这样呢?这就是为什么有一个与 cv 一起使用的互斥锁。你能告诉minimal reproducible example你有什么吗? afaik 条件变量的重点是处理虚假唤醒的情况 【参考方案1】:如果调用wait()
的代码编写不正确,它确实可能会错过唤醒。但这有点反常。通常的成语是:
lock the mutex
while the condition is not satisfied
wait on the condition variable
信号线程应该在发出信号之前锁定互斥体:
lock the mutex
signal the condition variable
等待条件变量会在等待期间解锁互斥锁。但是,当等待调用返回时,互斥锁将被锁定。因此,在虚假唤醒时,等待线程将持有互斥锁,直到它恢复等待。当等待线程持有互斥锁时,发信号线程不能发信号给条件变量。当等待线程实际等待时,互斥锁被解锁,信号线程可以继续发出信号;等待线程会得到信号,一旦信号线程释放互斥体,等待线程将恢复执行。
所以,不,正确的代码不会错过任何信号。但是如果等待线程释放互斥体并在检查其条件的过程中重新获取它,则信号可能在等待线程调用等待之前发生,并且信号将丢失。不要那样做。
【讨论】:
"当等待线程持有互斥锁时,信号线程不能向条件变量发出信号。" - 这就是我所缺少的。谢谢!【参考方案2】:虚假唤醒意味着它可能会虚假唤醒,然后必须继续等待。
这根本不是指错过事件的可能性,因为如果这是真的,那将毫无用处。
这个链接提供了关于cv和wait方法的详细解释:
https://www.codeproject.com/Articles/598695/Cplusplus-threads-locks-and-condition-variables
// print a starting message
std::unique_lock<std::mutex> locker(g_lockprint);
std::cout << "[logger]\trunning..." << std::endl;
// loop until end is signaled
while(!g_done)
std::unique_lock<std::mutex> locker(g_lockqueue);
g_queuecheck.wait(locker, [&]()return !g_codes.empty(););
// if there are error codes in the queue process them
while(!g_codes.empty())
std::unique_lock<std::mutex> locker(g_lockprint);
std::cout << "[logger]\tprocessing error: " << g_codes.front() << std::endl;
g_codes.pop();
【讨论】:
以上是关于如果被虚假唤醒,消费者线程是不是会收到 condition_variable 通知信号的主要内容,如果未能解决你的问题,请参考以下文章