丢失唤醒:如果生产者先获取互斥量怎么办?
Lost wake-up: What if the producer acquires the mutex first?
我正在尝试了解使用条件变量时丢失唤醒的问题。我相信我在下面使用了正确的设计模式。消费者:
lock the mutex
while the condition is not satisfied
wait on the condition variable
consume
unlock the mutex
制作人:
lock the mutex
produce
unlock the mutex
signal the condition variable (notify consumer)
我的问题是:如果消费者先获取互斥锁,那没问题——直到消费者在 wait() 释放互斥锁,生产者才能获取互斥锁,因此生产者在消费者实际等待之前将无法通知()。 但是如果生产者在消费者之前获得互斥量怎么办?那么它可以在消费者等待之前通知()。据我了解,下面的代码没有解决这个问题。有人可以验证这一点吗?如果确实没有,如何才能绝对保证不存在丢失唤醒的问题?
#include <iostream>
#include <thread>
#include <mutex>
#include <thread>
#include <condition_variable>
using namespace std;
class Foo {
mutex m;
condition_variable cv;
bool consumerReady;
public:
Foo() {
consumerReady = false;
}
void producer() {
{
unique_lock<mutex> ul(m);
cout << "produced"<<endl;
consumerReady = true;
}
cv.notify_one();
}
void consumer() {
unique_lock<mutex> ul(m);
cv.wait(ul, [this]{ return consumerReady; });
cout<<"consumed"<<endl;
consumerReady = false;
}
};
int main() {
Foo* z = new Foo();
thread t1(&Foo::producer, z);
thread t2(&Foo::consumer, z);
t1.join();
t2.join();
return 0;
}
But what if the producer acquires the mutex before the consumer? Then it could notify() before the consumer is waiting.
没问题。
您的 cv.wait(ul, [this]{ return consumerReady; });
与
相同
while(not consumerReady) cv.wait(ul)
因此,首先检查实际的 consumerReady
变量,只有在未设置时才会进入等待模式。
您遗漏了制作人的关键步骤:
lock the mutex
_make the condition TRUE_
signal the condition variable
如果 prodcer 在前,那么你是对的:信号会丢失。但这并没有什么坏处,因为消费者会看到条件已经为真,因此它不会等待信号。
我正在尝试了解使用条件变量时丢失唤醒的问题。我相信我在下面使用了正确的设计模式。消费者:
lock the mutex
while the condition is not satisfied
wait on the condition variable
consume
unlock the mutex
制作人:
lock the mutex
produce
unlock the mutex
signal the condition variable (notify consumer)
我的问题是:如果消费者先获取互斥锁,那没问题——直到消费者在 wait() 释放互斥锁,生产者才能获取互斥锁,因此生产者在消费者实际等待之前将无法通知()。 但是如果生产者在消费者之前获得互斥量怎么办?那么它可以在消费者等待之前通知()。据我了解,下面的代码没有解决这个问题。有人可以验证这一点吗?如果确实没有,如何才能绝对保证不存在丢失唤醒的问题?
#include <iostream>
#include <thread>
#include <mutex>
#include <thread>
#include <condition_variable>
using namespace std;
class Foo {
mutex m;
condition_variable cv;
bool consumerReady;
public:
Foo() {
consumerReady = false;
}
void producer() {
{
unique_lock<mutex> ul(m);
cout << "produced"<<endl;
consumerReady = true;
}
cv.notify_one();
}
void consumer() {
unique_lock<mutex> ul(m);
cv.wait(ul, [this]{ return consumerReady; });
cout<<"consumed"<<endl;
consumerReady = false;
}
};
int main() {
Foo* z = new Foo();
thread t1(&Foo::producer, z);
thread t2(&Foo::consumer, z);
t1.join();
t2.join();
return 0;
}
But what if the producer acquires the mutex before the consumer? Then it could notify() before the consumer is waiting.
没问题。
您的 cv.wait(ul, [this]{ return consumerReady; });
与
while(not consumerReady) cv.wait(ul)
因此,首先检查实际的 consumerReady
变量,只有在未设置时才会进入等待模式。
您遗漏了制作人的关键步骤:
lock the mutex
_make the condition TRUE_
signal the condition variable
如果 prodcer 在前,那么你是对的:信号会丢失。但这并没有什么坏处,因为消费者会看到条件已经为真,因此它不会等待信号。