c++ - std::condition_variable 和 std::mutex 是如何工作的?
问题描述
我正在阅读这个 std::condition_variable
例子:
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex m;
std::condition_variable cv;
std::string data;
bool ready = false;
bool processed = false;
void worker_thread()
{
// Wait until main() sends data
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []{return ready;});
// after the wait, we own the lock.
std::cout << "Worker thread is processing data\n";
data += " after processing";
// Send data back to main()
processed = true;
std::cout << "Worker thread signals data processing completed\n";
// Manual unlocking is done before notifying, to avoid waking up
// the waiting thread only to block again (see notify_one for details)
lk.unlock();
cv.notify_one();
}
int main()
{
std::thread worker(worker_thread);
data = "Example data";
// send data to the worker thread
{
std::lock_guard<std::mutex> lk(m);
ready = true;
std::cout << "main() signals data ready for processing\n";
}
cv.notify_one();
// wait for the worker
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []{return processed;});
}
std::cout << "Back in main(), data = " << data << '\n';
worker.join();
}
让我们专注于开头:
std::thread worker(worker_thread);
在这里,我们开始工作,它将立即锁定互斥锁:
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []{return ready;});
然后,我们将互斥锁锁定在 main 上以更改ready
{
std::lock_guard<std::mutex> lk(m);
ready = true;
std::cout << "main() signals data ready for processing\n";
}
但是我们怎么可能到达线路ready=true
呢?互斥锁被m
工作线程阻塞,因此该行将std::lock_guard<std::mutex> lk(m);
等待互斥锁m
解锁。据我了解,当互斥锁被锁定并且我们尝试锁定它时,我们将等到它被解锁。但是,它永远不会被解锁,因为工作线程正在等待,因此不会释放它。
解决方案
在您附加的链接中,请注意以下内容
等待操作以原子方式释放互斥体并暂停线程的执行。
因此这条线
cv.wait(lk, []{return ready;});
释放互斥锁并暂停线程的执行,直到通知条件变量、超时到期(带wit_for()
)或发生虚假唤醒,因此线程被唤醒,并且互斥锁被原子地重新获取
推荐阅读
- json - 如何访问嵌套 JSON 对象的多个值?
- node.js - 如果 req.body 为空,则从数据库中删除字段
- ruby-on-rails-5 - ParameterMissing:参数丢失或值为空:apartment_param
- python - 使用 jinja 使用块内容时如何包含不同的 js 和 css 文件
- shiny - 在 Ubuntu 机器上闪亮
- python - 具有不同输入大小的 Keras 共享层
- python - Python:根据另一列中的值更新列表中的列
- java - 如何使用 java 流将平面对象转换为预期对象
- android - 从代码中添加联系人后,phoneBook 在 android 中的句点 (.) 之后附加空格
- android - 如果已经给出输入数字属性,如何在软键盘中启用操作按钮?