1. 为什么需要 std::future?
在传统的 C++ 多线程编程中,我们经常遇到一个棘手的问题:如何安全地获取线程执行的结果?假设你创建了一个线程来计算斐波那契数列的第 30 项,你当然希望最终能拿到这个计算结果。但问题来了,线程是异步执行的,主线程如何知道子线程什么时候计算完成?又该如何拿到这个结果?
我曾经在一个项目中就踩过这样的坑。当时我天真地使用了一个全局变量来存储线程的计算结果,结果程序运行时偶尔会崩溃。后来发现是因为多个线程同时读写这个全局变量导致了数据竞争。这种通过共享变量来传递结果的方式,不仅代码难以维护,而且存在严重的安全隐患。
std::future 的出现就是为了解决这个问题。它就像你和线程之间的一个约定:线程承诺在未来某个时刻会给你一个结果,而你可以通过 future 对象来查询或等待这个结果。这种机制完全避免了显式的共享数据,从根本上解决了数据竞争的问题。
提示:std::future 是 C++11 引入的重要特性,它提供了一种线程安全的方式来获取异步操作的结果。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. std::future 的基本用法
2.1 创建 future 对象
std::future 通常不会直接创建,而是通过以下三种方式获得:
- 通过 std::async 启动异步任务
- 通过 std::packaged_task 包装可调用对象
- 通过 std::promise 手动设置值
让我们看一个最简单的例子,使用 std::async 创建异步任务:
cpp复制#include <iostream>
#include <future>
int calculate() {
// 模拟耗时计算
std::this_thread::sleep_for(std::chrono::seconds(1));
return 42;
}
int main() {
// 启动异步任务
std::future<int> fut = std::async(std::launch::async, calculate);
// 在主线程做其他事情...
std::cout << "正在等待结果..." << std::endl;
// 获取结果(会阻塞直到结果就绪)
int result = fut.get();
std::cout << "计算结果: " << result << std::endl;
return 0;
}
这个例子展示了 std::future 最典型的用法。std::async 启动了一个异步任务,并返回一个 future 对象。当我们需要结果时,调用 get() 方法即可。
2.2 future 的状态管理
每个 future 对象都有一个关联的共享状态
