Rust async/await
async/await 与 Future 模型:异步函数返回 Future,需执行器驱动;.await 点协作式让出。
#type / concept
#status / growing
#tech / dev
#resource / rust
[!info] 关联笔记
Rust async/await
这个概念为什么出现
高并发 I/O 若一连接一线程成本高。
Rust 的 async/await 提供零成本风格的异步语法:async fn 变成实现 Future 的状态机,由运行时轮询。
[!abstract] 一句话理解
async fn返回impl Future;.await在 Future 未就绪时让出执行;没有执行器,Future 不会自己跑起来。
最小可运行示例
场景:可组合的异步“假 I/O”——顺序等待两个步骤
无引入第三方运行时的情况下,用标准库手动 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> {
let _ = 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- 执行器/反应器:调度与 I/O 事件
Pin:自引用状态机安全- 取消:通常 drop Future
async 是并发模型,不等于多线程并行;可与多线程运行时组合。
设计动机
- 语言级 async 语法
- 与所有权/借用兼容
- 生态可插拔运行时(Tokio、async-std 等)
边界与误区
- 在 async 中阻塞会卡住工作线程
- 不要
std::thread::sleep代替tokio::time::sleep asynctrait 历史演进(RPITIT/async fn in trait 等按版本)
[!warning] 常见误区:认为 async fn 会自动并行 顺序
.await是串行;并行要用join!/spawn。
工程实践
- I/O 密集服务用 async 运行时
- CPU 密集放到
spawn_blocking或独立线程池 - 统一错误与超时
- 取消与优雅关闭一起设计
本节总结
- Future + 执行器
- await 协作式
- 生态运行时承接工程细节
自测题
- 为什么
main不能直接.await? - Future 被 drop 意味着什么?
参考答案
- main 默认不是 async 上下文,且需要执行器。
- 取消/停止该异步计算(需库支持协作点)。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| The Async Book | 官方社区书 | async 模型 |
| std::future::Future | 标准库 | Future |
| Tokio tutorial | 生态 | 实践 |