std::promise 和 std::future 是单次值传递的同步契约:一设一取,自动阻塞,不可重用、无超时、不支持多写,set_value 仅能调用一次,get() 为消费型操作,多次调用非法。
std::promise 和 std::future 不是“通信机制”,而是**单次值传递的同步契约**:一个线程设值(set_value),另一个线程取值(get),中间自动阻塞等待。它不支持多次传值、也不支持取消或超时重试——别当 channel 用。
这是最常踩的坑。重复调用 set_value 会抛出 std::future_error,错误码为 std::future_errc::promise_already_satisfied。
std::promise?必须加锁,或改用 std::atomic + 标志位判断set_exception 替代 set_value,否则 future.get() 会直接 rethrowset_value 或 set_exception?future.get() 将永远阻塞(无超时)get() 是“消费型”操作:首次调用后,std::future 对象进入无效状态(valid() == false),再次调用 get() 抛出 std::future_er(
rorstd::future_errc::no_state)。
std::future 多次调用 get() —— 它不是缓存,是一次性取货单std::shared_future,它支持多次 get(),底层引用同一状态wait_for(std::chrono::seconds(0)) == std::future_status::ready
std::promise 对象本身(如成员函数 get_future())不是线程安全的;但其关联的共享状态(由 std::future 和 std::promise 共同持有)对 set_value/get 是线程安全的。
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 生命周期。