std::promise 是 C++11 引入的并发编程工具,用于在线程间传递异步操作的结果(值或异常)。它与 std::future 配合使用,构成生产者-消费者模型:生产者线程通过 promise 设置结果,消费者线程通过关联的 future 获取结果。
核心作用
- 结果传递
允许一个线程存储值或异常,另一个线程通过 future 获取。 - 线程同步
future.get() 会阻塞消费者线程,直到生产者设置结果。 - 异常传递
可将异常从生产者线程传递到消费者线程。
基本用法
步骤 1:创建 promise 和 future
#include <future>
#include <iostream>
int main() {
std::promise<int> prom;
std::future<int> fut = prom.get_future();
}
步骤 2:生产者线程设置值
void producer(std::promise<int>&& prom) {
int result = 42;
prom.set_value(result);
}
步骤 3:消费者线程获取值
void consumer(std::future<int>&& fut) {
try {
int result = fut.get();
std::cout << "Result: " << result << std::endl;
} catch (const std::exception& e) {
std::cerr << "Exception: " << e.what() << std::endl;
}
}
步骤 4:启动线程
int main() {
std::promise<int> prom;
std::future<int> fut = prom.get_future();
std::thread producer_thread(producer, std::move(prom));
std::thread consumer_thread(consumer, std::move(fut));
producer_thread.join();
consumer_thread.join();
}
关键特性
- 一次性使用
set_value() 或 set_exception() 只能调用一次。future.get() 只能调用一次(第二次会抛 std::future_error)。
- 移动语义
promise 和 future 不可复制,只能移动(使用 std::move)。 - 异常安全
如果 promise 析构时未设置结果,future.get() 会抛 std::future_error(错误码 broken_promise)。
完整示例:计算平方
#include <iostream>
#include <future>
#include <thread>
#include <cmath>
void compute_square(std::promise<double>&& prom, double x) {
try {
if (x < 0) throw std::domain_error("Negative input");
double result = x * x;
prom.set_value(result);
} catch (...) {
prom.set_exception(std::current_exception());
}
}
int main() {
std::promise<double> prom;
std::future<double> fut = prom.get_future();
double input = 4.0;
std::thread worker(compute_square, std::move(prom), input);
try {
double result = fut.get();
std::cout << input << "^2 = " << result << std::endl;
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
}
worker.join();
return 0;
}
适用场景
- 线程池任务返回结果
将 promise 与任务绑定,通过 future 获取结果。 - 超时控制
结合 future.wait_for() 实现超时等待。 - 复杂异步操作
多个 promise 可组合为复杂工作流(需配合 std::async 或手动管理)。
注意事项
- 生命周期管理
确保 promise 存活直至结果被设置。 - 性能考量
频繁创建 promise/future 可能影响性能,优先考虑线程池。 - 替代方案
简单任务可用 std::async(内部自动管理 promise/future)。