未解锁互斥量时通知condition_variable仍可正常运行的原因解析
为什么notify_one前不解锁互斥量代码仍能正常运行?
先贴出你提到的代码:
#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(); }
你的疑惑完全可以理解——毕竟直觉上会觉得,工作线程拿着锁notify,主线程被唤醒后拿不到锁,等工作线程释放锁时主线程已经休眠了,没人再唤醒它。但实际运行正常的原因,是你对cv.wait()的完整执行流程理解有遗漏,咱们一步步拆解:
核心细节:cv.wait(lk, pred)的完整逻辑
当线程调用带谓词的wait时,整个流程是:
- 自动释放持有的互斥锁,进入休眠等待唤醒
- 被notify唤醒后,先重新获取互斥锁(如果拿不到就阻塞在这里,不会再次休眠)
- 获取锁之后,检查谓词
pred是否为true:- 如果为true,wait返回,线程持有锁继续执行
- 如果为false,自动释放锁,回到休眠状态等待下一次唤醒
对应到你的代码流程
- 工作线程执行notify_one时:确实还握着互斥锁,主线程被notify唤醒后,尝试获取互斥锁——但此时锁被工作线程持有,所以主线程阻塞在获取锁的步骤,而不是回到休眠等待notify的状态。
- 工作线程结束函数:worker_thread执行到末尾,局部变量
std::unique_lock<std::mutex> lk被销毁,销毁时会自动释放互斥锁。 - 主线程拿到锁:此时主线程终于获取到互斥锁,接着检查谓词
[]{return processed;}——工作线程已经把processed设为true了,谓词满足,wait直接返回,主线程继续执行后续逻辑。
你之前担心的“主线程休眠后没人唤醒”根本不会发生,因为主线程从来没回到等待notify的休眠状态,它只是在等互斥锁而已。等锁被释放后,条件已经满足,自然就继续走下去了。
另外补充一句:虽然notify操作不需要持有互斥锁,但即使持有锁时调用也完全没问题——因为唤醒的线程会先处理锁的获取,再检查条件,不会出现你担心的“唤醒后又休眠没人管”的情况。
内容的提问来源于stack exchange,提问作者SungJinKang
相关产品推荐
相关产品推荐

