C++类内无限循环方法多线程实现、线程销毁及join放置问题
问题核心原因
- 原
thread_foo函数末尾的sleep(MAX_INT)会阻塞调用线程,导致main函数调用完第一个thread_foo就卡住,无法执行后续逻辑 - C++ 没有安全的强制销毁线程的接口,暴力终止线程会触发资源泄漏、死锁等未定义行为,必须通过退出标志让线程主动结束运行
- 单个成员变量无法存储多个线程的句柄,需要用容器存储所有启动的线程对象和对应的退出控制标志
修正后的实现代码
#include <thread> #include <atomic> #include <vector> #include <utility> // 假设stuff是你自定义的类型,这里先做别名声明 using stuff = const char*; class Test{ public: // 存储所有启动的线程和对应的退出标志 std::vector<std::pair<std::thread, std::atomic<bool>>> thread_list; void foo(stuff stuff, std::atomic<bool>& exit_flag){ // 循环判断退出标志,没有收到退出信号就继续运行 while(!exit_flag.load()) { does_stuff(stuff); } } void thread_foo(stuff stuff){ // 新建线程对应的退出标志,初始为false std::atomic<bool> exit_flag = false; // 启动线程,把退出标志的引用传进去 std::thread th(&Test::foo, this, stuff, std::ref(exit_flag)); // 把线程和对应的退出标志存入容器 thread_list.emplace_back(std::move(th), std::move(exit_flag)); // 这里不需要加sleep,启动完直接返回,main就不会被阻塞 } // 销毁指定下标的线程,传0就是销毁第一个创建的线程 void destroy_thread(size_t idx) { if (idx >= thread_list.size()) return; auto& [th, exit_flag] = thread_list[idx]; if (!th.joinable()) return; // 发送退出信号 exit_flag.store(true); // 等待线程退出回收资源 th.join(); // 从容器中移除对应的条目 thread_list.erase(thread_list.begin() + idx); } // 析构函数回收所有剩余线程,避免进程退出时线程还在运行 ~Test() { for (auto& item : thread_list) { auto& [th, exit_flag] = item; if (th.joinable()) { exit_flag.store(true); th.join(); } } } private: // 你的业务逻辑函数 void does_stuff(stuff s) { // 实现你的业务逻辑 } };
main函数调用示例
int main() { Test t; // 两次调用会启动两个并行运行的线程,调用完直接返回,main不会阻塞 t.thread_foo("random stuff1"); t.thread_foo("random stuff2"); // 这里可以继续执行main的其他逻辑,不会被阻塞 // ...其他业务代码... // 需要销毁第一个线程的时候调用 t.destroy_thread(0); // ...其他业务代码... // main函数退出前t的析构函数会自动回收所有剩余的线程,不需要手动处理 return 0; }
关键问题说明
- 并行不阻塞实现逻辑:
thread_foo启动线程后直接返回,没有额外的阻塞逻辑,main调用两次thread_foo后两个线程会在后台并行运行,main可以继续执行后续代码 join()的放置位置:- 销毁单个线程时,在给线程发送退出信号后调用join,等待线程退出回收资源
- 所有剩余线程的join放在类的析构函数中,当Test对象生命周期结束时自动回收所有线程,避免资源泄漏
- 销毁第一个线程的注意事项:必须通过退出标志通知线程主动退出,不能直接销毁
std::thread对象,未join的std::thread对象销毁时会直接触发程序崩溃
内容的提问来源于stack exchange,提问作者aliruk
相关产品推荐
相关产品推荐

