# 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进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。