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

C++ condition variable wait疑问及读写线程死锁问题求助

问题解答

1. 关于condition_variable::wait带谓词的阻塞问题

当std::condition_variable::wait传入谓词时,如果谓词初始即为true,wait不会发生阻塞:

  • wait会先在持有锁的情况下检查谓词结果;
  • 若谓词为true,直接返回,不会释放锁也不会进入等待状态;
  • 若谓词为false,才会释放锁并进入等待,被唤醒后重新获取锁,再次检查谓词,直到谓词为true才返回。

2. 死锁原因分析与解决方案

死锁根源

你的代码存在线程执行顺序的竞态条件:
假设写线程先抢到锁:

  1. 写线程加锁后,检查谓词m_reader_state == PrepDone,此时读线程尚未设置该状态,条件不满足,写线程释放锁进入等待;
  2. 读线程随后抢到锁,设置m_reader_state = PrepDone,接着检查谓词m_writer_state == BlockWriteDone,此时写线程尚未设置该状态,读线程释放锁进入等待;
  3. 两个线程均陷入等待,且都没有机会触发对方的notify操作,最终形成死锁。

修正后的代码

核心调整:读线程在设置完自身状态后,先notify写线程,再进入等待;写线程完成状态设置后,及时notify读线程。

写线程代码

mylock.lock();
// 等待读线程进入PrepDone状态
m_writer_cv.wait(mylock, [this] {
    return this->m_reader_state == ReaderState::PrepDone;
});
// 设置写线程状态为BlockWriteDone
m_writer_state = WriterState::BlockWriteDone;
// 通知读线程:写线程已准备完成
m_reader_cv.notify_one();
mylock.unlock();

读线程代码

mylock.lock();
// 设置读线程状态为PrepDone
m_reader_state = ReaderState::PrepDone;
// 通知写线程:读线程已准备完成
m_writer_cv.notify_one();
// 等待写线程进入BlockWriteDone状态
m_reader_cv.wait(mylock, [this] {
    return this->m_writer_state == WriterState::BlockWriteDone;
});
mylock.unlock();
// 若后续无需通知写线程,可移除该行
// m_writer_cv.notify_one();

额外注意事项

  • 必须通过wait的谓词检查状态,禁止在wait外单独判断状态,避免虚假唤醒导致的逻辑错误;
  • notify_one/notify_all可在锁内或锁外执行:锁内执行能确保状态更新对等待线程可见,锁外执行性能更优(需确保状态更新已通过mutex同步);
  • 确保condition_variable与对应的mutex绑定使用,禁止跨线程混用不同的锁和条件变量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 17:15:33