本页目录

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

// 多线程 (默认)
#[tokio::main]
async fn main() { ... }

// 等价于:
fn main() {
    tokio::runtime::Builder::new_multi_thread()
        .worker_threads(num_cpus::get())  // 默认: CPU 核数
        .enable_all()                     // IO + 时间
        .build().unwrap()
        .block_on(async { ... });
}

// 单线程 (用于简单场景, 如不需要跨线程同步)
#[tokio::main(flavor = "current_thread")]
async fn main() { ... }

spawn: 独立的并发 task

let handle = tokio::spawn(async move {
    let result = do_heavy_work().await;
    println!("{}", result);
});
// 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

tokio::select! {
    result = long_running_op() => { /* 处理结果 */ }
    _ = tokio::signal::ctrl_c() => { /* Ctrl+C 信号 */ }
}

任何一个 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