You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 20:06:02