std::future 和 std::promise 是 C++11 提供的单次值传递同步机制,用于异步任务结果传递;std::promise 设置值,std::future 获取值,二者配对且仅能各操作一次,不可拷贝,需配合移动语义使用。
std::future 和 std::promise 是 C++11 引入的、用于在线程间**单次传递一个值**的同步机制。它们不是通用消息队列,也不是替代 std::mutex 的工具,而是专为“我启动一个异步任务,稍后取它的返回值”这种场景设计的。
一个 std::promise 对象持有一个可写入的共享状态;调用 set_value()(或 set_exception())后,其关联的 std::future 就能通过 get() 读取结果。关键约束是:
std::future::get() 只能调用一次,第二次会抛出 std::future_error(错误码为 std::future_errc::no_state 或 std::future_errc::future_already_retrieved)std::promise::set_value() 也只能调用一次;重复调用会终止程序(std::terminate)std::promise 和 std::future 之间通过移动语义转移共享状态,不能拷贝常见误用:在多个线程里反复调用 get() 试图“轮询”,这会导致崩溃或未定义行为。
典型模式是主线程创建 std::promise,把它的 std::future 移交给工作线程(或反过来),再由某一方负责设置值、另一方负责获取。注意:std::promise 本身不带线程安全保证,但它的 set_* 成员函数是线程安全的;std::future::get() 是线程安全的阻塞等待。
int main() {
std::promise p;
std::future f = p.get_future(); // 此处转移共享状态
std::thread t([&p]() {
std::this_thread::sleep_for(std::chrono::seconds(1));
p.set_value(42); // 工作线程设置值
});
int result = f.get(); // 主线程阻塞等待并取值(自动 move)
t.join();
return result;
}
手动管理 容易出错,尤其当你要传函数对象时。
std::packaged_task 把可调用对象和配套的 std::promise 绑定在一起,构造时自动生成 std::future,调用时自动触发 set_value():
set_value(),减少逻辑遗漏风险int main() {
std::packaged_task task([]{ return 123; });
std::future f = task.get_future();
std::thread t(std::move(task));
int x = f.get(); // 阻塞直到线程执行完 task 并返回
t.join();
return x;
}
它不解决多生产者、多消费者、重复读写、流式数据等问题。例如:
std::queue + std::mutex + std::condition_variable
std::atomic 或 std::condition_variable
std::future::get() 返回的是右值引用,会自动 move最常被忽略的一点:future 的阻塞等待(get()、wait())无法被中断,也没有超时重试的默认机制——如果 promise 永远不被 set,线程就永远卡住。生产环境务必配合 wait_for() 或 wait_until() 使用。