You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

未解锁互斥量时通知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,自动释放锁,回到休眠状态等待下一次唤醒

对应到你的代码流程

  1. 工作线程执行notify_one时:确实还握着互斥锁,主线程被notify唤醒后,尝试获取互斥锁——但此时锁被工作线程持有,所以主线程阻塞在获取锁的步骤,而不是回到休眠等待notify的状态。
  2. 工作线程结束函数:worker_thread执行到末尾,局部变量std::unique_lock<std::mutex> lk被销毁,销毁时会自动释放互斥锁。
  3. 主线程拿到锁:此时主线程终于获取到互斥锁,接着检查谓词[]{return processed;}——工作线程已经把processed设为true了,谓词满足,wait直接返回,主线程继续执行后续逻辑。

你之前担心的“主线程休眠后没人唤醒”根本不会发生,因为主线程从来没回到等待notify的休眠状态,它只是在等互斥锁而已。等锁被释放后,条件已经满足,自然就继续走下去了。

另外补充一句:虽然notify操作不需要持有互斥锁,但即使持有锁时调用也完全没问题——因为唤醒的线程会先处理锁的获取,再检查条件,不会出现你担心的“唤醒后又休眠没人管”的情况。

内容的提问来源于stack exchange,提问作者SungJinKang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 17:02:41