C++ condition variable wait疑问及读写线程死锁问题求助
问题解答
1. 关于condition_variable::wait带谓词的阻塞问题
当std::condition_variable::wait传入谓词时,如果谓词初始即为true,wait不会发生阻塞:
- wait会先在持有锁的情况下检查谓词结果;
- 若谓词为true,直接返回,不会释放锁也不会进入等待状态;
- 若谓词为false,才会释放锁并进入等待,被唤醒后重新获取锁,再次检查谓词,直到谓词为true才返回。
2. 死锁原因分析与解决方案
死锁根源
你的代码存在线程执行顺序的竞态条件:
假设写线程先抢到锁:
- 写线程加锁后,检查谓词
m_reader_state == PrepDone,此时读线程尚未设置该状态,条件不满足,写线程释放锁进入等待; - 读线程随后抢到锁,设置
m_reader_state = PrepDone,接着检查谓词m_writer_state == BlockWriteDone,此时写线程尚未设置该状态,读线程释放锁进入等待; - 两个线程均陷入等待,且都没有机会触发对方的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
相关产品推荐
相关产品推荐

