当希望线程终止时,删除包含运行中线程的类是否安全?
关于删除包含运行中线程的类是否安全的问题分析
首先直接给结论:这种做法既不可行也不安全,咱们结合你的代码慢慢说清楚。
先看你代码里的操作:你启动线程后调用了detach(),这一步会把线程和std::thread对象解绑——意思是,线程会在后台独立运行,哪怕worker对象被销毁,这两个std::thread成员析构时也不会有问题(因为detach过的线程对象析构不会触发std::terminate)。但问题出在这几个地方:
线程不受控,无法确保终止
detach之后,你完全失去了对这两个线程的控制权:没办法用join()等待它们结束,也没有标准的安全方式主动终止线程。这意味着哪怕你销毁了worker对象,这两个线程还会继续跑满50秒才结束,期间你完全没法干预。潜在的未定义行为风险
如果你的线程函数里访问了worker类的成员变量(哪怕现在示例里没有,实际场景大概率会有),那当worker对象被销毁后,这些成员变量已经被释放,线程再去访问就会触发内存错误、野指针等未定义行为,程序随时可能崩溃或者出现诡异的bug。
再说说你析构函数里的疑问:join()到底要不要?
- 如果你的线程没有调用
detach(),那必须在std::thread对象析构前调用join()或者detach(),否则std::thread的析构函数会直接调用std::terminate(),程序直接崩溃。 - 但你这里已经detach了,所以析构时不用join也不会崩溃,但这根本不是解决“希望线程终止”的办法。
正确的做法应该是这样
想要安全地让线程终止并销毁类对象,你需要给线程一个“停止信号”,让线程主动退出,然后等待它结束,再销毁对象。比如用原子变量做停止标志:
#include <thread> #include <atomic> #include <chrono> class worker { std::thread thread1; std::thread thread2; std::atomic<bool> stop_flag{false}; // 原子变量保证线程间同步 public: worker() {} void start() { thread1 = std::thread([this]() { while (!stop_flag.load()) { // 这里做线程的实际工作 std::this_thread::sleep_for(std::chrono::milliseconds(100)); } }); thread2 = std::thread([this]() { while (!stop_flag.load()) { // 这里做线程的实际工作 std::this_thread::sleep_for(std::chrono::milliseconds(100)); } }); } ~worker() { stop_flag.store(true); // 通知线程可以停止了 // 检查线程是否可join,避免重复join或者join未启动的线程 if (thread1.joinable()) { thread1.join(); // 等待线程1完全退出 } if (thread2.joinable()) { thread2.join(); // 等待线程2完全退出 } } };
最后总结一下
- 直接销毁包含detach线程的类对象,虽然不会立刻崩溃,但线程会继续运行,且存在访问已销毁对象的风险,完全不符合你“希望线程终止”的需求。
- 安全的方式是通过同步机制(比如原子标志、条件变量)让线程主动退出,然后调用
join()等待线程结束,再让类对象析构,这样才能确保线程和类的生命周期正确衔接。
内容的提问来源于stack exchange,提问作者code_fodder
相关产品推荐
相关产品推荐

