c++ - c++ 中的 std::condition_variable::wait
问题描述
我对互斥锁、锁定和等待有点困惑。
这是我的代码:
void producer(std::mutex* m, std::condition_variable* cv,bool* signal) {
std::this_thread::sleep_for(std::chrono::seconds(1));
m->lock();
*signal = true;
m->unlock();
std::this_thread::sleep_for(std::chrono::seconds(3));
cv->notify_one();
printf("notify one\n");
std::this_thread::sleep_for(std::chrono::seconds(10000));
}
void consumer(std::mutex*m, std::condition_variable* cv, bool* signal, int index) {
if(index == 2) std::this_thread::sleep_for(std::chrono::seconds(2));
std::unique_lock<std::mutex> lk(*m);
cv->wait(lk, [&] { return (*signal); });
printf("consumer %d passes this point!\n", index);
std::this_thread::sleep_for(std::chrono::seconds(10000));
}
int main() {
bool signal = false;
std::mutex m;
std::condition_variable cv;
std::thread th1(producer, &m, &cv, &signal);
std::thread th2(consumer, &m, &cv, &signal, 1);
std::thread th3(consumer, &m, &cv, &signal, 2);
th1.join();
th2.join();
th3.join();
return 0;
}
std::this_thread::sleep_for
添加以解释我的问题。有生产者、消费者1和消费者2。我认为这段代码应该如下工作:
- consumer1 相遇
std::unique_lock<std::mutex> lk(*m);
,因此它锁定。 - 消费者 1 满足
cv->wait
。因为初始值为signal
isfalse
,所以 consumer1 被阻塞,锁被释放。 - 生产者遇到
m->lock();
,*signal = true;
,m->unlock();
和sleep_for
. 因此,signal
变为true
。 - 消费者 2 满足
std::unique_lock<std::mutex> lk(*m);
和cv->wait(lk, [&] { return (*signal); });
。因为signal
是true
,这个线程只是通过它。于是,printf("consumer %d passes this point!\n", index);
被执行。 - 制片人见面
cv->notify_one();
。消费者 1 已解锁并检查情况。因为signal
isture
,consumer1 可以通过这一点。因此,consumer1 满足printf
.
因此,我的预期结果是
consumer 2 passes this point!
notify one
consumer 1 passes this point!
然而,真正的结果是
consumer 2 passes this point!
notify one
似乎 consumer1 不能通过cv->wait(lk, [&] { return (*signal); });
,即使notify_one()
被调用并且条件得到满足。我的理解有什么问题吗?
解决方案
您没有在consumer
例行程序中释放锁定。下面的代码符合预期:
#include <thread>
#include <chrono>
#include <condition_variable>
#include <mutex>
void producer(std::mutex* m, std::condition_variable* cv,bool* signal) {
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::unique_lock<std::mutex> lk(*m);
*signal = true;
}
std::this_thread::sleep_for(std::chrono::seconds(3));
cv->notify_all();
printf("notify one\n");
std::this_thread::sleep_for(std::chrono::seconds(5));
}
void consumer(std::mutex*m, std::condition_variable* cv, bool* signal, int index) {
if(index == 2) std::this_thread::sleep_for(std::chrono::seconds(2));
{
std::unique_lock<std::mutex> lk(*m);
cv->wait(lk, [&] { return (*signal); });
}
printf("consumer %d passes this point!\n", index);
std::this_thread::sleep_for(std::chrono::seconds(5));
}
int main() {
bool signal = false;
std::mutex m;
std::condition_variable cv;
std::thread th1(producer, &m, &cv, &signal);
std::thread th2(consumer, &m, &cv, &signal, 1);
std::thread th3(consumer, &m, &cv, &signal, 2);
th1.join();
th2.join();
th3.join();
return 0;
}
注意周围的括号std::unique_lock<std::mutex> lk(*m);
以提供本地范围。
推荐阅读
- c# - 向 Entity 类添加版本控制
- ios - Value of type '[Book]?' has no member 'append'
- vba - 如何使用 winhttp 和 VBA 处理 302 错误
- c# - 是否可以在 Visual Studio Code 中构建和测试多目标 c# dotnet 项目?
- java - @JoinColumnS 涉及以一对一关系获取 EAGER
- pyspark - 在决策树分类器上拟合 RDD 数据时出错
- python - 从熊猫数据框中删除大量列
- objective-c - 为什么我会根据字符串构造或在不同环境中运行时获得不同的 NSString UTF-8 表示?
- c - 如何创建一个包含指向另一个未指定类型的结构的指针的结构?
- python-3.x - Tkinter Mac 应用程序无法正常工作