Rust async/await
async/await 与 Future 模型:异步函数返回 Future,需执行器驱动;.await 点协作式让出。
#concept
#growing
#dev
#rust
[!info] related notes
Rust async/await
这个概念为什么出现
高并发 I/O 若一连接一线程成本高。
Rust 的 async/await 提供零成本风格的异步语法:async fn 变成实现 Future 的状态机,由运行时轮询。
[!abstract] 一句话理解
async fn返回impl Future;.await在 Future 未就绪时让出执行;没有执行器,Future 不会自己跑起来。
最小语法示例:创建但不驱动 Future
场景:可组合的异步“假 I/O”——顺序等待两个步骤
以下程序只证明 async 函数可以创建 Future,不演示执行器或真实 I/O。标准库提供 Future/poll 协议,运行时集成见 Tokio。
// 业务意图:表达“先校验、再计费”两步异步流程的代码形状。
// 教学点:async fn 返回 Future;需要执行器才能运行。
// 注意:本示例在 stable 上若无执行器,仅展示函数形态,不直接在 main await。
async fn validate_order(id: u64) -> Result<(), String> {
if id == 0 {
return Err("bad id".into());
}
Ok(())
}
async fn charge(id: u64) -> Result<u32, String> {
validate_order(id).await?;
Ok(100) // 金额分
}
// 生产环境:
// #[tokio::main]
// async fn main() { charge(1).await.unwrap(); }
fn main() {
println!("async functions compile to futures; run them with an executor (e.g. Tokio)");
let _future = charge(1); // 创建 Future 但未驱动
}
建议运行:cargo run
期望输出:
async functions compile to futures; run them with an executor (e.g. Tokio)
结合场景再看三个关注点
- Future 惰性:创建 ≠ 执行
.await只在 async 上下文- 错误用
Result+?同样适用
核心概念与准确模型
- Future 的 poll 返回 Pending/Ready;Pending 时需安排在可推进后唤醒任务。Future 完成后不应再随意 poll
- await 只有等待的 Future 返回 Pending 才暂停当前任务;立即 Ready 的 await 不保证让出执行权
- 执行器/反应器:调度与 I/O 事件
Pin:自引用状态机安全- 丢弃未完成的 Future 会停止继续轮询并释放其持有状态,但不会回滚已发生的 I/O 或保证独立后台工作停止;丢弃 Tokio JoinHandle 会分离任务,不是取消该任务
async 是并发模型,不等于多线程并行;可与多线程运行时组合。
设计动机
- 语言级 async 语法
- 与所有权/借用兼容
- 生态可插拔运行时(Tokio、async-std 等)
边界与误区
- 在 async 中阻塞会卡住工作线程
- 不要
std::thread::sleep代替tokio::time::sleep asynctrait 历史演进(RPITIT/async fn in trait 等按版本)
[!warning] 常见误区:认为 async fn 会自动并行 顺序 await 通常顺序推进;join! 可在同一任务内并发轮询多个 Future,不保证多核并行。spawn 创建独立任务,是否并行取决于执行器与负载。
工程实践
- I/O 密集服务用 async 运行时
- 阻塞工作可移到 spawn_blocking;持续 CPU 密集工作应限制并发或用专门线程池,已开始的阻塞任务通常不能靠 abort 中断
- 统一错误与超时
- 取消与优雅关闭一起设计
本节总结
- Future + 执行器
- await 协作式
- 生态运行时承接工程细节
自测题
- 为什么
main不能直接.await? - Future 被 drop 意味着什么?
参考答案
- main 默认不是 async 上下文,且需要执行器。
- 不再推进这个 Future 并清理其状态;已经发生的外部副作用不撤销,也不能据此断言它启动的其他任务已停止。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| The Async Book | 官方社区书 | async 模型 |
| std::future::Future | 标准库 | Future |
| Tokio tutorial | 生态 | 实践 |