std::future的get()会阻塞且只能调用一次,顺序调用导致并发失效;需用wait_for()+valid()轮询(仅async/packaged_task创建的future支持);shared_future允许多消费者共享结果;C++26的when_all/when_any和then()才原生支持聚合。

std::future 的 get() 调用会阻塞,不能直接 for 循环等待多个
你写了个循环:for (auto& f : futures) { f.get(); },结果程序卡在第一个 get() 上,后面全没执行——因为 get() 是阻塞且只能调用一次的。每个 std::future 必须单独、显式地等待其就绪,而且一旦调用 get(),该 future 就失效了,不能再用。
更麻烦的是:多个异步任务耗时不同,如果按顺序 get(),后一个快的任务反而要等前一个慢的,白白浪费并发优势。
用 wait_for() 轮询 + valid() 判断状态
想非阻塞地检查多个 std::future 是否完成,得靠 wait_for() 配合 valid()。注意:不是所有 future 都支持 wait_for() —— 只有由 std::async 或 std::packaged_task 创建的才带状态轮询能力;std::promise::get_future() 返回的 future 不支持 wait_for()(它没有内部线程状态管理)。
立即学习“C++免费学习笔记(深入)”;
-
wait_for(std::chrono::milliseconds(0))是“零等待”轮询,立即返回std::future_status::ready、::timeout或::deferred - 每次调用前必须先检查
f.valid(),否则对已 move 出或已get()过的future调用wait_for()会抛std::future_error - 轮询间隔不宜太密(如
1ms),否则 CPU 空转;也不宜太长(如1s),影响响应性;常见折中是10–50ms
用 std::shared_future 实现多消费者共享结果
如果你需要把同一个异步结果分发给多个线程(比如日志、监控、主逻辑都依赖同一计算),别重复创建多个 std::future。用 std::shared_future 替代:
- 从任意
std::future调用.share()得到一个std::shared_future -
shared_future可被拷贝,每个副本都能独立调用get()或wait() - 底层只有一份状态,所有副本看到的结果一致,且不会因某个副本调用
get()而使其他副本失效 - 适用于“一个生产者,多个消费者”的聚合场景,比如统一采集多个传感器数据后广播给多个处理模块
C++26 的 then() 和 when_all() 才真正解决聚合问题
在 C++26 之前,你得手动管理 vector of future、轮询、异常捕获、结果收集——代码冗长且易错。C++26 引入了 std::when_all() 和 std::when_any(),这才是面向聚合的原生方案:
-
std::when_all(f1, f2, f3)返回一个新的std::future<std::tuple<T1,T2,T3>>,所有输入 future 都就绪后才就绪 -
std::when_any(f1, f2, f3)返回std::future<std::variant<...>>,任一就绪即触发 - 它们都支持链式调用
.then(),结果自动传递,异常自动沿链传播,无需手动 try/catch 每个 future - 注意:这些是 C++26 新特性,当前主流编译器(GCC 14/Clang 18)需开启
-std=c++2b并确认是否启用实验性支持
真正容易被忽略的点是:std::promise 和 std::packaged_task 创建的 future 不支持 wait_for(),但 std::async 默认策略下创建的可以——这个差异直接影响你能否做无锁轮询。别假设所有 future 行为一致。


















