191 lines
4.8 KiB
Markdown
191 lines
4.8 KiB
Markdown
哈哈,好的,你现在已经把 **线程、互斥、原子**都啃完了,剩下的就是 **“有返回值的并发”**——也就是 `<future>` / `<async>` 的领域了。
|
||
我给你整理一份 **速查表+说明**,保证看完就能用。
|
||
|
||
---
|
||
|
||
# 一、`std::async` 基本概念
|
||
|
||
> **作用**:开启一个任务,并且自动管理线程,可以**拿返回值**。
|
||
> 它本质是“带未来值的线程”。
|
||
|
||
### 1️⃣ 基本用法
|
||
|
||
```cpp
|
||
#include <future>
|
||
#include <iostream>
|
||
using namespace std;
|
||
|
||
int work(int x) { return x * x; }
|
||
|
||
int main() {
|
||
future<int> f = async(work, 5);
|
||
int result = f.get(); // 阻塞直到返回值就绪
|
||
cout << result << endl; // 25
|
||
}
|
||
```
|
||
|
||
### 参数详解
|
||
|
||
```cpp
|
||
async(launch::policy policy, Callable f, Args... args)
|
||
```
|
||
|
||
* `policy` 可选:
|
||
|
||
* `launch::async` → 必在新线程运行
|
||
* `launch::deferred` → 等到调用 `get()` 才执行(懒加载)
|
||
* 可以用 `|` 混合
|
||
* `f` → 函数或 lambda
|
||
* `args...` → 参数
|
||
|
||
### 返回值
|
||
|
||
* `std::future<R>`
|
||
* `get()` 得到实际返回值
|
||
* 阻塞直到任务完成
|
||
* 调用一次 `get()` 后 future 失效
|
||
|
||
---
|
||
|
||
# 二、`std::future` 基本操作
|
||
|
||
| 函数 | 作用 | 返回值 |
|
||
| ------------------------ | -------- | --------------- |
|
||
| `get()` | 阻塞等待结果 | `R` |
|
||
| `wait()` | 阻塞直到准备好 | void |
|
||
| `wait_for(duration)` | 阻塞指定时间 | `future_status` |
|
||
| `wait_until(time_point)` | 阻塞到指定时间点 | `future_status` |
|
||
| `valid()` | 是否有有效任务 | bool |
|
||
|
||
`future_status` 枚举:
|
||
|
||
```cpp
|
||
std::future_status::ready // 已就绪
|
||
std::future_status::timeout // 超时
|
||
std::future_status::deferred // 延迟执行
|
||
```
|
||
|
||
---
|
||
|
||
# 三、`std::promise`(future 的搭档)
|
||
|
||
> **作用**:手动给 future 设置值
|
||
|
||
```cpp
|
||
#include <future>
|
||
|
||
std::promise<int> p;
|
||
std::future<int> f = p.get_future();
|
||
|
||
// 子线程
|
||
std::thread([&p](){
|
||
p.set_value(42);
|
||
}).detach();
|
||
|
||
// 主线程
|
||
int val = f.get(); // 42
|
||
```
|
||
|
||
### 关键点
|
||
|
||
* `set_value()` → 给 future 赋值
|
||
* `set_exception()` → 把异常传给 future
|
||
* `get_future()` → 得到与 promise 绑定的 future
|
||
|
||
---
|
||
|
||
# 四、组合 async + future + lambda(最常用)
|
||
|
||
```cpp
|
||
auto f = async([](int x){ return x*2; }, 10);
|
||
cout << f.get(); // 20
|
||
```
|
||
|
||
* 不用手动管理线程
|
||
* 可以拿返回值
|
||
* 自动 join / 管理
|
||
|
||
---
|
||
|
||
# 五、等待与超时(高级)
|
||
|
||
```cpp
|
||
future<int> f = async(work, 5);
|
||
if(f.wait_for(500ms) == future_status::ready) {
|
||
cout << f.get() << endl;
|
||
} else {
|
||
cout << "还没完成" << endl;
|
||
}
|
||
```
|
||
|
||
* 非阻塞方式获取结果
|
||
* 用于并行计算 + 超时控制
|
||
|
||
---
|
||
|
||
# 六、`future` 全家桶速查表
|
||
|
||
| 类型 / 函数 | 作用 | 返回值 |
|
||
| ------------------------ | ------------- | ------------- |
|
||
| `std::future<T>` | 保存异步任务结果 | — |
|
||
| `get()` | 阻塞获取结果 | `T` |
|
||
| `wait()` | 阻塞直到就绪 | void |
|
||
| `wait_for(duration)` | 阻塞指定时间 | future_status |
|
||
| `wait_until(time_point)` | 阻塞到指定时间点 | future_status |
|
||
| `valid()` | 是否有效 | bool |
|
||
| `std::promise<T>` | 手动设置 future 值 | — |
|
||
| `set_value()` | 设置值 | void |
|
||
| `set_exception()` | 设置异常 | void |
|
||
| `get_future()` | 获取 future | future<T> |
|
||
| `std::async()` | 开启任务 | future<T> |
|
||
|
||
---
|
||
|
||
# 七、使用建议
|
||
|
||
1️⃣ **如果需要返回值 → 用 async 或 promise/future**
|
||
2️⃣ **不用 async 就直接 thread + mutex/atomic → 仅做“干活”**
|
||
3️⃣ **async + lambda 最简洁**,避免手动 join / detach
|
||
4️⃣ **多线程大计算 → future + async + wait_for**,保证不会死锁
|
||
|
||
---
|
||
|
||
# 八、示例:多线程计算 + 获取返回值
|
||
|
||
```cpp
|
||
#include <future>
|
||
#include <vector>
|
||
#include <iostream>
|
||
using namespace std;
|
||
|
||
int work(int x){ return x*x; }
|
||
|
||
int main(){
|
||
vector<future<int>> tasks;
|
||
for(int i=1; i<=4; i++){
|
||
tasks.push_back(async(work, i));
|
||
}
|
||
for(auto &f: tasks){
|
||
cout << f.get() << " ";
|
||
}
|
||
cout << endl;
|
||
}
|
||
```
|
||
|
||
输出:`1 4 9 16`(顺序可能一样也可能不同)
|
||
|
||
---
|
||
|
||
总结一句话:
|
||
|
||
> **thread → 干活**
|
||
> **mutex/atomic → 防抢/快抢**
|
||
> **future/async → 干活 + 拿结果**
|
||
> **promise → 未来值的手动操控**
|
||
|
||
---
|
||
|
||
我可以帮你 **把之前的“拷贝大文件”项目升级成 async + future 版本**,实现 **多线程拷贝 + 返回每个块的字节数 + 进度统计**,让你真正把线程+future全套用起来。
|
||
|
||
你想试吗?
|