C++ thread与condition_variable:程序是否可能永久无法终止?
C++条件变量程序终止问题及修改验证
你认为下方的C++源代码可能永久无法终止:假设所有waiter线程均已进入等待状态,此时waker线程调用notify_all(),线程t1被唤醒并执行任务,其他线程虽被唤醒,但因mutex被t1占用而回到等待状态,最终永久休眠,导致程序无法结束。你修改了waiter函数,在执行完任务后解锁并调用notify_all(),想确认修改是否正确。
原代码
#include <chrono> #include <condition_variable> #include <mutex> #include <thread> #include <vector> using namespace std; mutex m; condition_variable cv; bool isStop = false; void waiter() { unique_lock<mutex> ul(m); cv.wait(ul, []() { return isStop; }); // ...do something... } void waker() { this_thread::sleep_for(chrono::seconds(1)); unique_lock<mutex> ul(m); isStop = true; ul.unlock(); cv.notify_all(); } void main() { vector<thread> ts; for (int i = 0; i < 100; ++i) ts.emplace_back(waiter); thread w(waker); for (auto& t : ts) t.join(); w.join(); }
修改后的waiter函数
void waiter() { unique_lock<mutex> ul(m); cv.wait(ul, []() { return isStop; }); // ...do something... ul.unlock(); cv.notify_all(); }
解答
首先纠正一个误解:原代码并不会出现你担心的永久休眠问题。
原因在于cv.wait(ul, []() { return isStop; })的工作机制:线程被唤醒后,会先重新获取互斥锁,然后再次检查谓词条件(也就是isStop是否为true)。当waker线程已经把isStop设为true,所有被notify_all()唤醒的waiter线程,哪怕一开始没抢到锁,等锁被释放后,重新获取锁时会发现isStop已经是true,直接退出等待逻辑,不会再回到休眠状态。
再看你的修改:
- 手动调用
ul.unlock()属于冗余操作,unique_lock作为局部变量,函数执行完毕时会自动释放锁。 - 每个waiter线程都调用
cv.notify_all()完全没必要,会产生大量无意义的通知,徒增系统开销。
结论:你的修改是不必要的,原代码本身逻辑正确,不会出现永久无法终止的问题。
内容的提问来源于stack exchange,提问作者user19800684
相关产品推荐
相关产品推荐

