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

C++主线程等待所有async线程完成的实现问题

解决主线程等待所有std::async线程完成的问题

你的问题核心是主线程没等std::async创建的异步线程执行完就读取结果,导致res为空;但如果在每个线程创建后立刻调用wait(),又会让线程串行执行,失去并行效果。

解决方案

在所有异步线程创建完成后,批量等待它们执行结束,而非逐个等待。可以把等待逻辑封装到类中,或在主线程获取结果前主动触发等待。

修改后的代码示例

方式1:在consume函数末尾等待所有线程

#include <iostream>
#include <vector>
#include <unistd.h>     // sleep
#include <future>
#include <mutex>
#include <thread>

using namespace std;

class Myclass {
private:
    std::vector<int> resources;
    std::vector<int> res;

    std::mutex resMutex;
    std::vector<std::future<void>> m_futures;
public:
    Myclass() {
        for (int i = 0; i < 10; i++) resources.push_back(i);   // 添加任务
        res.reserve(resources.size());
    }

    void consume() {
        for (int i = 0; i < resources.size(); i++) {
            m_futures.push_back(std::async(std::launch::async, &Myclass::work, this, resources[i]));
        }
        // 等待所有异步线程执行完毕
        for (auto& fut : m_futures) {
            fut.wait();
        }
    }

    void work(int x) {
        sleep(1);     // 模拟耗时操作

        std::lock_guard<std::mutex> lock(resMutex);
        res.push_back(x);
        printf("%d be added.---done by %ld.\n", x, std::this_thread::get_id());
    }

    std::vector<int> &getRes() { return res;}
};

int main() {
    Myclass obj;
    obj.consume();
    auto& res = obj.getRes(); // 用引用避免不必要的拷贝
    cout << "Done. res.size = " << res.size() << endl;
    for (int i : res) cout << i << " ";
    cout << "\nmain thread over\n";
}

方式2:单独提供等待函数,由主线程调用

如果不想在consume中直接等待,可给类添加一个waitForAll成员函数:

// 在Myclass的public区域添加
void waitForAll() {
    for (auto& fut : m_futures) {
        fut.wait();
    }
}

然后修改main函数:

int main() {
    Myclass obj;
    obj.consume();
    obj.waitForAll(); // 主动等待所有线程完成
    auto& res = obj.getRes();
    cout << "Done. res.size = " << res.size() << endl;
    for (int i : res) cout << i << " ";
    cout << "\nmain thread over\n";
}

原理说明

  • std::async(std::launch::async)会创建新线程执行任务,返回的std::future可跟踪线程状态。
  • 在所有线程创建完成后循环调用future.wait(),主线程会阻塞直到所有异步任务执行完毕,同时所有异步线程保持并行运行,不会互相阻塞。
  • 原代码中auto res = obj.getRes();会拷贝整个vector,改用引用auto& res = obj.getRes();更高效,也能确保读取到最新结果。

修改后的输出示例

所有异步线程的输出会先打印,随后主线程输出最终结果:

0 be added.---done by 140709267197696.
1 be added.---done by 140709258805056.
...(其他线程输出)
9 be added.---done by 140709225636032.
Done. res.size = 10
0 1 2 3 4 5 6 7 8 9 
main thread over

内容的提问来源于stack exchange,提问作者tom

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 18:10:27