在 C++ 中,std::promise
和 std::future
是用于处理异步操作和并发编程的重要组件。它们通常一起使用,以便在一个线程中设置值,并在另一个线程中获取这些值。这种机制使得线程之间的通信变得简单且安全。
1. std::promise
std::promise
是一个模板类,可以用来为某个值提供一个“承诺”,这种值通常是计算结果。当你在一个线程中完成某项工作时,可以利用 std::promise
来设置这个结果。其他线程可以通过与之关联的 std::future
来访问这个结果。
基本语法:
#include <future>
2. std::future
std::future
用于获取未来的值,它与 std::promise
直接相关联。通过 std::future
,你可以等待异步操作的结果,同时保证线程安全。
基本语法:
#include <future>
3. 使用示例
以下是一个简单的示例,展示了如何使用 std::promise
和 std::future
在不同线程之间传递值。
#include <iostream>
#include <thread>
#include <future>
#include <chrono>
void calculateFactorial(int n, std::promise<int> prom) {
int result = 1;
for (int i = 1; i <= n; ++i) {
result *= i;
}
// 将计算结果传递给 Promise
prom.set_value(result);
}
int main() {
// 创建一个 promise 和对应的 future
std::promise<int> prom;
std::future<int> fut = prom.get_future(); // 从 promise 获取 future
// 启动一个线程来计算阶乘
std::thread t(calculateFactorial, 5, std::move(prom));
// 等待结果并输出
std::cout << "Calculating factorial...\n";
int result = fut.get(); // 阻塞直到结果准备好
std::cout << "Factorial: " << result << std::endl;
// 等待线程结束
t.join();
return 0;
}
4. 代码解析
-
创建 Promise 和 Future:
std::promise<int>
创建一个promise
对象,用于传递int
类型的值。prom.get_future()
返回与prom
关联的future
对象。
-
启动线程:
- 使用
std::thread
来运行calculateFactorial
函数。在这个函数中会执行阶乘的计算,并将结果存储到 Promise 中。
- 使用
-
阻塞等待结果:
- 在主线程中调用
fut.get()
,这将阻塞当前线程,直到Promise
被满足(即设置了值)。
- 在主线程中调用
-
输出结果:
- 一旦
result
可用,程序将输出计算的阶乘结果。
- 一旦
-
清理线程:
- 使用
t.join()
确保主线程等待子线程完成执行。
- 使用
5. 异常处理
如果在 set_value
之前发生异常,你可以使用 set_exception
来处理错误:
void safeCalculateFactorial(int n, std::promise<int> prom) {
try {
if (n < 0) throw std::runtime_error("Negative input");
int result = 1;
for (int i = 1; i <= n; ++i) {
result *= i;
}
prom.set_value(result);
} catch (...) {
prom.set_exception(std::current_exception());
}
}
6. 总结
std::promise
和std::future
提供了 C++ 中简洁的方式来进行线程间通信。- 它们允许在一个线程中生成值,并在另一个线程中安全地获取这些值。
- 使用 Promise 和 Future 时,注意处理异常情况,以确保程序的健壮性。