std::future.get()会永久阻塞且仅能调用一次,错误时rethrow异常;非阻塞判断用wait_for(0);多future用when_any;临时future导致deferred任务不执行;shared_future支持多次get但有同步开销;promise的set_*必须且只能调用一次。

std::future.get() 会阻塞,但不是唯一取值方式
std::future 的核心作用是「等待并获取异步任务结果」,get() 最常用,但它一旦调用就**永久阻塞直到就绪**,且只能调用一次。如果任务出错(比如抛了异常),get() 会直接 rethrow,不加 try-catch 就崩。
- 想非阻塞判断是否完成?用
wait_for(std::chrono::milliseconds(0))或wait_until,返回std::future_status::ready才安全调get() - 多个 future 要等任意一个就绪?别循环轮询
wait_for,改用std::experimental::when_any(C++17 起有std::future等价物需配合std::shared_future和条件变量模拟) -
get()后再调一次?触发std::future_error,错误码是std::future_errc::no_state
std::async 启动后,future 不持有线程所有权
std::async 返回的 std::future 和底层线程是松耦合的——它不管理线程生命周期,只管结果同步。这意味着:
- 如果
std::future对象提前析构(比如函数返回前没保存),而任务是std::launch::async模式,线程仍会继续运行;但如果是std::launch::deferred,任务根本不会执行,get()时才懒执行 - 常见误操作:把
std::async结果赋给临时std::future,比如std::async([]{...}).get()—— 这里 future 是纯右值,构造完立刻析构,deferred 模式下任务永远不跑 - 确保任务执行完毕,最稳妥的是显式保存 future 对象,哪怕只是
auto f = std::async(...); f.get();
std::shared_future 支持多次 get,但有开销
普通 std::future 移动后原对象失效,不能复制;需要共享结果(比如多个线程都读同一结果),必须转成 std::shared_future。
- 转换只能通过
share()成员函数:std::shared_future<int> sf = f.share();</int>,之后f变成无效状态(f.valid() == false) -
std::shared_future::get()可多次调用,但每次仍会阻塞到首次就绪为止;后续调用直接返回缓存值或重抛首次异常 - 内部用了引用计数和锁,频繁拷贝
std::shared_future对象本身开销不大,但高并发下get()的同步点可能成瓶颈,别在 tight loop 里反复调
std::promise + std::future 配合时,set_* 必须只调一次
手动控制结果时,std::promise 是生产端,std::future 是消费端。关键约束是:set_value、set_exception、set_exception_at_thread_exit 三者**有且仅能调用一次**。
立即学习“C++免费学习笔记(深入)”;
- 重复调
set_value?触发std::future_error,错误码std::future_errc::promise_already_satisfied - promise 对象析构前没 set?future 的
get()永远阻塞,变成死锁隐患;建议在 promise 作用域结束前明确 set,或用 RAII 包装(比如局部std::promise+ lambda 捕获后置 set) - 跨线程传递 promise 时,注意它不可拷贝,只能移动;若需多处触发,得用
std::shared_ptr<:promise>></:promise>包一层
真正麻烦的不是语法,而是状态机:future 的 ready / deferred / invalid 三种状态切换隐含在对象生命周期、移动语义和线程调度里。漏掉一次 valid() 检查,或者多调一次 get(),错误就藏在运行时,还不好复现。











