【发布时间】:2021-08-08 19:25:09
【问题描述】:
#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()
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []{return ready;});
std::cout << "Worker thread is processing data\n";
data += " after processing";
processed = true;
std::cout << "Worker thread signals data processing completed\n";
//lk.unlock(); /// here!!!!!!!!!!!
cv.notify_one();
}
int main()
{
std::thread worker(worker_thread);
data = "Example data";
{
std::lock_guard<std::mutex> lk(m);
ready = true;
std::cout << "main() signals data ready for processing\n";
}
cv.notify_one();
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []{return processed;});
}
std::cout << "Back in main(), data = " << data << '\n';
worker.join();
}
我不知道为什么这段代码在 worker_thread 中的 notify_one 之前没有解锁就可以工作。
我想如果我在通知之前不解锁,唤醒主线程将再次阻塞,因为互斥锁仍由 worker_thread 持有。
之后worker_thread将解锁互斥锁(因为unique_lock在销毁时解锁互斥锁)。
那么没有人可以唤醒沉睡的主线程。
但此代码运行良好,无需在通知之前解锁互斥锁。
这是如何工作的????
(我看了cppreference cmets,但看不懂)
【问题讨论】:
-
条件变量不能停止等待,直到互斥锁被释放,因为退出等待需要重新获取互斥锁。解锁后通知效率更高,但不是必需的。解锁前通知将使通知以正常的互斥锁获取/阻塞时间为准。
-
当主线程被唤醒时,它不再在 CV 上等待——它现在在互斥体上等待。当互斥锁被解锁时,主线程被唤醒,因为这只是互斥锁的正常场景,不需要唤醒信号。
-
@JohnFilleau 理论上是的,但实际上操作系统已为此进行了优化,并且没有降级。
-
@sergey 这是个好消息!
标签: c++ multithreading c++11