std::promise和std::future用于线程间异步传递结果,promise设置值或异常,future获取结果,二者通过共享状态关联,支持阻塞获取和超时等待,适用于生产者-消费者模型。

在C++中,std::future 和 std::promise 是用于异步任务之间传递结果的核心工具。它们提供了一种机制:一个线程可以将计算结果“承诺”给另一个线程,而接收方可以通过“未来”对象来获取这个值,即使它尚未准备好。
std::promise 与 std::future 的基本关系
std::promise 是一个可写入一次的对象,用来设置某个值或异常;std::future 是其对应的只读句柄,用来获取那个值。两者通过共享状态关联。
简单来说:
- 你在一个线程中创建一个 std::promise
,然后把它的 std::future 给另一个线程。 - 当工作完成后,调用 promise.set_value(),future 就能获取到该值。
- 如果发生错误,可以用 promise.set_exception() 通知 future。
基本使用示例
下面是一个简单的例子,展示如何用 promise 和 future 在两个线程间通信:
立即学习“C++免费学习笔记(深入)”;
#include#include #include void producer(std::promise && prom) { try { // 模拟耗时操作 std::this_thread::sleep_for(std::chrono::seconds(2)); int result = 42; prom.set_value(result); // 设置结果 } catch (...) { prom.set_exception(std::current_exception()); } } void consumer(std::future && fut) { std::cout << "等待结果...\n"; int value = fut.get(); // 阻塞直到值可用 std::cout << "收到结果:" << value << "\n"; } int main() { std::promise prom; std::future fut = prom.get_future(); std::thread t1(producer, std::move(prom)); std::thread t2(consumer, std::move(fut)); t1.join(); t2.join(); return 0; }
输出:
等待结果... 收到结果:42
注意:promise 和 future 都只能移动,不能复制,因为每个共享状态只能有一个生产者和一个消费者。
超时与非阻塞检查
除了 get() 这种阻塞方式,future 还支持带超时的等待:
- future.wait_for(duration):等待指定时间,返回状态(ready、timeout 等)。
- future.wait_until(time_point):等待到某个时间点。
- future.wait():一直阻塞直到就绪。
示例:检查是否完成而不阻塞太久
std::futurefut = prom.get_future(); auto status = fut.wait_for(std::chrono::milliseconds(100)); if (status == std::future_status::ready) { std::cout << "结果已就绪:" << fut.get() << "\n"; } else if (status == std::future_status::timeout) { std::cout << "还在处理中,稍后再试\n"; }
与 std::async 的区别
std::async 是更高层的异步接口,会自动启动任务并返回一个 future。而 promise/future 更灵活,允许你手动控制何时设置结果。
适用场景对比:
- 用 std::async:想快速启动一个函数并获取返回值。
- 用 std::promise + std::thread:需要精细控制线程逻辑,比如事件驱动、回调注入、跨线程响应等。
异常传递
promise 不仅能传递正常值,还能传递异常。这使得错误处理更安全:
try {
throw std::runtime_error("出错了!");
} catch (...) {
prom.set_exception(std::current_exception());
}
consumer 中调用 fut.get() 会重新抛出这个异常,可以被正常 catch。
注意事项与常见陷阱
- 每个 std::promise 只能调用一次 set_value 或 set_exception,多次调用会抛出 std::future_error。
- 如果不设置值就析构 promise,future 会收到 std::future_errc::broken_promise 异常。
- 确保 promise 和 future 正确移动,避免因拷贝导致编译错误。
- 长时间阻塞 get 调用可能影响性能,建议结合 wait_for 使用超时机制。











