← [ BACK_TO_NOTES ]

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)

结合场景再看三个关注点

  1. Future 惰性:创建 ≠ 执行
  2. .await 只在 async 上下文
  3. 错误用 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
  • async trait 历史演进(RPITIT/async fn in trait 等按版本)

[!warning] 常见误区:认为 async fn 会自动并行 顺序 await 通常顺序推进;join! 可在同一任务内并发轮询多个 Future,不保证多核并行。spawn 创建独立任务,是否并行取决于执行器与负载。

工程实践

  1. I/O 密集服务用 async 运行时
  2. 阻塞工作可移到 spawn_blocking;持续 CPU 密集工作应限制并发或用专门线程池,已开始的阻塞任务通常不能靠 abort 中断
  3. 统一错误与超时
  4. 取消与优雅关闭一起设计

本节总结

  • Future + 执行器
  • await 协作式
  • 生态运行时承接工程细节

自测题

  1. 为什么 main 不能直接 .await?
  2. Future 被 drop 意味着什么?
参考答案
  1. main 默认不是 async 上下文,且需要执行器。
  2. 不再推进这个 Future 并清理其状态;已经发生的外部副作用不撤销,也不能据此断言它启动的其他任务已停止。

延伸阅读与资料来源

资料类型支撑内容
The Async Book官方社区书async 模型
std::future::Future标准库Future
Tokio tutorial生态实践
创建于 2026/7/15 更新于 2026/10/7
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本