本页目录
tokio 运行时
tokio 的 reactor(基于 epoll/kqueue/IOCP)负责异步 IO,executor 用 work-stealing 调度 Future 到多线程——两者合起来是 Rust 异步的事实标准运行时。
spawn把 Future 提交到线程池,select!同时等待多个异步操作——理解 reactor 和 executor 的分工就理解了 tokio 的性能模型。
tokio 的三层架构
flowchart TD
TASK["🧵 你的 async task<br/>tokio::spawn"]
TASK --> QUEUE["📋 Task Queue<br/>等待调度的 Future"]
QUEUE --> EXECUTOR["⚙️ Executor<br/>work-stealing scheduler<br/>一个 CPU 核心一个 worker thread"]
EXECUTOR --> REACTOR["🔌 Reactor<br/>epoll (Linux) / kqueue (macOS)<br/>IOCP (Windows)"]
REACTOR --> KERNEL["🐧 OS Kernel"]
REACTOR -.->|"IO 就绪 → 唤醒 task"| QUEUE
classDef user fill:#e3f2fd,stroke:#1565c0
classDef middle fill:#fff3e0,stroke:#ef6c00
classDef os fill:#f3e5f5,stroke:#7b1fa2
class TASK,QUEUE user
class EXECUTOR,REACTOR middle
class KERNEL os
Reactor:监听所有注册的 IO 源(socket, timer, signal)→ IO 就绪 → 通知对应的 task 被唤醒。
Executor:维护 task queue → 被唤醒的 task 重新获得 CPU time。
你的代码:值调用 async fn 和 .await,不直接与 reactor 或 executor 打交道。
两种 runtime
// 多线程 (默认)
async
// 等价于:
// 单线程 (用于简单场景, 如不需要跨线程同步)
async
spawn: 独立的并发 task
let handle = spawn;
// handle: JoinHandle — 可以 .await 获取返回值
let result = handle.await.unwrap;
spawn 的 task 可以在不同的 worker thread 上执行——它是真正的并发,不是协程。返回的 JoinHandle 是一个 Future,.await 它等待 task 完成。
Work Stealing Scheduler
每个 worker thread 有自己的 local task queue。当某个 worker idle 时,随机偷其他 worker 的 task。这比"一个全局 queue + 所有 worker 竞争"的模型更高效——减少了锁竞争,因为 local push/pop 是无锁的。
select!: 等待多个 Future
select!
任何一个 branch 完成 → 其他 branches 被取消(drop)。这是 async Rust 内置的取消模型——不需要显式的 cancellation token。被取消的 Future 的 Drop 实现负责清理资源。
参考
- tokio: docs.rs/tokio, tokio.rs
- async book: rust-lang.github.io/async-book
Keywords: tokio, reactor, executor, work stealing, spawn, select!, runtime, current_thread