RustInPractice(19):Tokio 异步基础
async 不是“自动开线程”。Rust 的 async fn 返回 Future,Future 只有被 runtime 轮询时才推进;遇到 .await 无法继续时,它让出执行权,其他任务可以运行。
RustInPractice 第 19 篇。对应 demo:
learning_guide的 async 子命令、thread_pool。下一篇讨论有界并发与后台任务。
一、Future 是惰性的描述
1 | async fn fetch_name() -> String { |
调用 fetch_name() 得到的是 Future,不会立刻执行。需要在 async 上下文 .await,并由 Tokio runtime 等 executor 轮询:
1 |
|
二、任务不是 OS 线程
1 | let first = tokio::spawn(async { 1 + 1 }); |
Tokio task 是 runtime 调度的轻量任务。大量等待网络或计时器的任务可复用少量 OS 线程;但 CPU 密集循环或阻塞文件操作会占住 runtime worker,应该使用专用线程池或 spawn_blocking。
三、取消是 drop,不是异常
一个 task 的 JoinHandle 被 abort,或 Future 被丢弃时,Future 会在下一个可取消点停止。资源仍会执行 Drop,但外部副作用可能已经完成一部分。因此要设计幂等操作、超时和明确的关闭信号。
tokio::select! 可等待多个事件中的第一个:超时、取消信号、channel 消息等。它是 async 服务优雅退出和请求超时的基本工具。
四、不要在 async 中阻塞
| 工作 | 合适方式 |
|---|---|
| 网络、Tokio timer、async channel | .await |
| 短小同步计算 | 直接执行 |
| CPU 密集或阻塞库调用 | spawn_blocking / 专用线程池 |
| 长时间持有同步 Mutex | 重构,避免跨 .await |
五、小结
- async 函数返回惰性 Future,runtime 负责轮询。
- Tokio task 不等于线程,适合高并发等待。
- Future drop 即取消,需要设计超时与幂等性。
- 阻塞工作不能占用 async runtime worker。
下一篇:Semaphore、背压与后台任务,限制并发比无限 spawn 更重要。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 WALL-E's Blog!










