为何condition_variable的析构函数会导致程序挂起?
为何condition_variable的析构函数会导致程序挂起?
嘿,这个问题的核心原因其实很明确:当你的全局条件变量触发析构时,还有线程正阻塞在它的wait调用上,咱们结合你的代码一步步说清楚:
首先先看你提供的最小复现代码(MRE):
#include <mutex> #include <condition_variable> #include <thread> #include <unistd.h> std::mutex mu; std::condition_variable cv; void test(){ std::unique_lock lk(mu); cv.wait(lk); } int main(){ std::thread(test).detach(); sleep(3); }
问题拆解
- 主线程启动了一个detach的后台线程,这个线程一启动就拿到互斥锁,然后卡在
cv.wait(lk)上——它一直在等待条件变量被唤醒,但主线程从头到尾都没调用cv.notify_one()或者cv.notify_all()来通知它。 - 主线程sleep3秒后就直接退出了,这时候全局的
cv和mu会被自动析构。而C++标准库的condition_variable底层通常是基于POSIX的pthread_cond_t实现的,对应的销毁函数pthread_cond_destroy有个硬性要求:调用它的时候,绝对不能有任何线程还在等待这个条件变量。 - 你的后台线程此时还死死卡在wait上,这就导致
pthread_cond_destroy阻塞,最终整个程序挂住,也就是你看到的卡在pthread_cond_destroy的情况。
解决思路
你可以从两个方向修复这个问题:
- 主线程退出前主动唤醒后台线程:在
sleep(3)之后加一段代码,通知条件变量让后台线程结束等待,比如:{ std::lock_guard<std::mutex> lk(mu); cv.notify_all(); } - 不要使用detach,改用join等待后台线程结束:把
std::thread(test).detach();改成std::thread t(test); t.join();,这样主线程会等后台线程完成后再退出,避免全局变量先于线程析构。
备注:内容来源于stack exchange,提问作者DarkRise
相关产品推荐
相关产品推荐

