您好,登录后才能下订单哦!
# C++11中promise future如何使用
## 一、引言
在现代多线程编程中,线程间的数据传递和同步是一个核心问题。C++11标准库引入的`<future>`头文件提供了一组强大的工具,其中`promise`和`future`是实现线程间通信的重要机制。本文将深入探讨这对组件的使用方法和原理。
## 二、基本概念
### 2.1 Promise-Future模型
Promise-Future模式是一种典型的异步编程模型,包含两个关键组件:
- **Promise(承诺)**:数据的生产者,负责设置共享状态的值
- **Future(未来)**:数据的消费者,用于获取共享状态的值
### 2.2 与其他机制对比
| 机制 | 通信方向 | 线程安全 | 数据传递方式 |
|---------------|---------|---------|-------------|
| promise/future | 单向 | 是 | 值传递 |
| condition_variable | 双向 | 需配合锁 | 通知机制 |
| atomic | 双向 | 是 | 直接访问 |
## 三、核心组件详解
### 3.1 std::promise
```cpp
template< class R > class promise;
主要成员函数:
- set_value()
:设置结果值
- set_exception()
:设置异常
- get_future()
:获取关联的future对象
template< class R > class future;
关键方法:
- get()
:获取结果(会阻塞直到结果就绪)
- valid()
:检查future是否有效
- wait()
:等待结果就绪
- wait_for()
/wait_until()
:带超时的等待
#include <iostream>
#include <future>
#include <thread>
void producer(std::promise<int> prom) {
std::this_thread::sleep_for(std::chrono::seconds(1));
prom.set_value(42); // 设置结果值
}
int main() {
std::promise<int> prom;
std::future<int> fut = prom.get_future();
std::thread t(producer, std::move(prom));
std::cout << "Waiting for value...\n";
std::cout << "Value: " << fut.get() << "\n";
t.join();
return 0;
}
void task_with_exception(std::promise<void> prom) {
try {
throw std::runtime_error("Error occurred!");
} catch(...) {
prom.set_exception(std::current_exception());
}
}
允许多次获取结果的future:
std::promise<int> prom;
std::shared_future<int> shared_fut = prom.get_future().share();
// 多个线程可以同时访问shared_fut
auto future = std::async(std::launch::async, []{
return std::string("Hello from async");
});
std::cout << future.get() << std::endl;
std::future<int> fut = /* ... */;
if(fut.wait_for(std::chrono::milliseconds(100)) ==
std::future_status::ready) {
// 结果已就绪
} else {
// 超时处理
}
promise和future通过共享状态(shared state)进行通信,该状态包含: - 结果值或异常 - 就绪标志 - 可能存在的等待线程
共享状态的创建和销毁遵循特定规则: - 由promise创建 - 最后一个引用它的future或promise销毁时释放
操作 | 典型耗时 |
---|---|
promise创建 | ~100ns |
future.get()无阻塞 | ~50ns |
future.get()有阻塞 | 取决于等待时间 |
std::future<Result> start_async_task() {
std::promise<Result> prom;
auto fut = prom.get_future();
std::thread([p = std::move(prom)]() mutable {
p.set_value(compute_result());
}).detach();
return fut;
}
void parallel_processing() {
std::promise<void> ready_promise;
std::shared_future<void> ready_future = ready_promise.get_future().share();
auto worker = [ready_future](int id) {
ready_future.wait(); // 等待开始信号
// 执行工作...
};
std::vector<std::thread> workers;
for(int i = 0; i < 4; ++i) {
workers.emplace_back(worker, i);
}
// 准备工作...
ready_promise.set_value(); // 启动所有worker
for(auto& t : workers) t.join();
}
问题1:多次调用set_value
std::promise<int> p;
p.set_value(1);
p.set_value(2); // 抛出std::future_error
解决:确保每个promise只设置一次值
问题2:忽略future返回值
std::async(std::launch::async, heavy_task); // 临时future被销毁会阻塞
解决:保存future对象或使用std::future的析构行为
当多个线程互相等待对方的promise时可能导致死锁。解决方法: 1. 统一设置/获取顺序 2. 使用超时机制 3. 考虑使用std::shared_future
auto make_ready_future(int value) {
std::promise<int> p;
auto f = p.get_future();
p.set_value(value);
return f;
}
template<typename F, typename... Args>
auto async_retry(F&& f, Args&&... args)
-> std::future<decltype(f(args...))>
{
std::promise<decltype(f(args...))> p;
auto fut = p.get_future();
std::thread([&]{
try {
p.set_value(f(args...));
} catch(...) {
p.set_exception(std::current_exception());
}
}).detach();
return fut;
}
Promise-Future机制为C++多线程编程提供了强大而灵活的工具,其特点包括: 1. 类型安全的线程间通信 2. 异常安全的错误传递 3. 灵活的结果获取方式
在实际应用中,开发者应当根据具体场景选择合适的同步机制,对于需要返回值传递的异步操作,promise/future通常是首选方案。
#include <iostream>
#include <future>
#include <thread>
#include <vector>
#include <numeric>
// 并行累加示例
double parallel_accumulate(std::vector<double>::iterator begin,
std::vector<double>::iterator end) {
auto len = end - begin;
if(len < 1000) {
return std::accumulate(begin, end, 0.0);
}
auto mid = begin + len/2;
auto handle = std::async(std::launch::async,
parallel_accumulate, mid, end);
double sum = parallel_accumulate(begin, mid);
return sum + handle.get();
}
int main() {
std::vector<double> values(10000, 1.0);
std::future<double> fut = std::async(std::launch::async,
parallel_accumulate,
values.begin(), values.end());
std::cout << "The sum is " << fut.get() << '\n';
return 0;
}
”`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。