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
相关产品推荐
相关产品推荐

