条件变量被通知但未持锁时的行为及示例中cv.wait的执行逻辑
条件变量收到通知但未获取锁时的行为分析
问题背景
当条件变量收到通知但尚未获取锁时会发生什么?针对以下代码,cv.wait()会执行什么逻辑?若consumer被producer通知后无法获取m_cnt锁,会无限尝试获取锁吗?
std::condition_variable cv; std::mutex m_cnt; int cnt = 0; void producer() { std::unique_lock<std::mutex> ul(m_cnt); cnt++; cv.notify_one(); std::this_thread::sleep_for(std::chrono::seconds(1)); } void consumer() { std::unique_lock<std::mutex> ul(m_cnt); cv.wait(ul, [] {return cnt > 0;}); // 关注这里 cnt--; }
核心逻辑分析
cv.wait(ul, predicate)的完整执行流程
- 初始阶段:调用
wait时,unique_lock已持有锁,wait会自动释放该锁,随后consumer线程进入条件变量的等待队列,阻塞等待通知。 - 收到通知后:consumer被唤醒,首先尝试重新获取
m_cnt锁——如果此时锁被producer持有(比如示例中producer调用notify_one后仍在sleep,锁未释放),consumer不会无限循环尝试,而是进入mutex的等待队列,和其他请求该锁的线程一样,等待锁被释放。 - 获取锁后的检查:当producer的
unique_lock析构(sleep结束后函数返回),锁被释放,consumer拿到锁后,会立即检查传入的谓词cnt > 0:- 如果谓词为
true(示例中此时cnt=1),wait返回,consumer继续执行后续的cnt--。 - 如果谓词为
false(比如出现虚假唤醒),wait会再次释放锁,回到条件变量的等待队列,继续等待下一次通知。
- 如果谓词为
针对示例的具体行为
示例中producer调用notify_one后,锁仍在自己手中,consumer收到通知后会尝试获取锁,但抢不到就进入mutex的等待队列,直到producer sleep结束、释放锁,consumer才能拿到锁,接着检查谓词并继续执行,不会出现无限尝试的情况。
内容的提问来源于stack exchange,提问作者5reep4thy
相关产品推荐
相关产品推荐

