std::promise 和 std::future 是单次值传递的同步契约:一设一取,自动阻塞,不可重用、无超时、不支持多写,set_value 仅能调用一次,get() 为消费型操作,多次调用非法。

std::promise 和 std::future 不是“通信机制”,而是**单次值传递的同步契约**:一个线程设值(set_value),另一个线程取值(get),中间自动阻塞等待。它不支持多次传值、也不支持取消或超时重试——别当 channel 用。
std::promise::set_value 必须且只能调用一次
这是最常踩的坑。重复调用 set_value 会抛出 std::future_error,错误码为 std::future_errc::promise_already_satisfied。
- 多个线程试图写同一个
std::promise?必须加锁,或改用std::atomic+ 标志位判断 -
异步任务可能失败?用
set_exception替代set_value,否则future.get()会直接 rethrow - 忘记调用
set_value或set_exception?future.get()将永远阻塞(无超时)
std::future::get() 会移动并销毁内部状态
get() 是“消费型”操作:首次调用后,std::future 对象进入无效状态(valid() == false),再次调用 get() 抛出 std::future_error(std::future_errc::no_state)。
- 不要保存
std::future多次调用get()—— 它不是缓存,是一次性取货单 - 需要共享结果?用
std::shared_future,它支持多次get(),底层引用同一状态 - 想非阻塞检查是否就绪?用
wait_for(std::chrono::seconds(0)) == std::future_status::ready
std::promise/std::future 不自带线程安全,但状态对象是线程安全的
std::promise 对象本身(如成员函数 get_future())不是线程安全的;但其关联的共享状态(由 std::future 和 std::promise 共同持有)对 set_value/get 是线程安全的。
立即学习“C++免费学习笔记(深入)”;
-
std::promise只能被一个线程调用set_value或set_exception—— 多线程写需外部同步 -
std::future的get()和wait_for()可在任意线程安全调用 - 别把同一个
std::promise对象传给多个线程去get_future()—— 每个get_future()返回新std::future,但共享状态只有一个
std::promiseprom; std::future fut = prom.get_future(); std::thread t([&prom]() { std::this_thread::sleep_for(std::chrono::seconds(1)); prom.set_value(42); // OK: 唯一写入点 }); t.detach(); // 主线程中: int val = fut.get(); // 阻塞直到 set_value,然后返回 42 // fut.get(); // ❌ runtime error: no_state
真正容易被忽略的是:这个契约没有超时语义,也没有重试路径;一旦 promise 被遗弃(未 set),future 就成了死锁源。生产环境建议用 std::packaged_task 包装可执行体,或直接上 std::async,它们自动管理 promise 生命周期。











