知其然,知其所以然
Rust 内部机制 2026-10-02

Async Runtime 做了什么

用不到 60 行标准库代码写一个单线程执行器(任务队列 + Waker + poll 循环 + 定时线程),验证异步运行时做了什么:3 个任务在同一线程交错运行,总耗时约 150 ms 而非 300 ms,poll 6 次;Pending → wake → 重新入队 → 再 poll 的完整路径;任务里 thread::sleep 卡住整个执行器;与 tokio current_thread(150 ms)对照。

Rust async 运行时 executor waker 真实验证 动画演示
Rust 内部机制 2026-10-02

async/await 状态机

async fn 的 Future 是状态机:大小取决于跨 await 保存的局部变量(空 1 字节、跨 await 的 1000 字节数组 1002 字节、3000 字节 3002 字节),而且看作用域而不是最后一次使用(放进内层块只有 2 字节);poll 4 次保存并恢复局部变量;完成后再 poll panic;递归要 Box::pin(E0733);自引用 Future 是 !Unpin(E0277)。

Rust async await 状态机 真实验证 动画演示
Rust 内部机制 2026-10-02

Tokio 任务调度

下载 tokio 验证任务调度:4 工作线程运行时上 1000 个任务分布在全部 4 个线程;同一任务的多次 poll 可能换线程(16 个里 12 个);current_thread 里 150 ms 无 await 计算让 ticker 推迟到 150 ms;多线程运行时里 ticker 在 20 ms 就开始;spawn_blocking 不占用运行时线程。

Rust tokio 调度 工作窃取 真实验证 动画演示
Rust 内部机制 2026-10-02

spawn 与 'static

真实验证 tokio::spawn 为什么要求 'static:借用局部变量的 async 块报 E0373;move、Arc、clone 三种修法;tokio::join! 在同一任务里并发可以借用;'static 的含义(拥有的值、字面量、Box::leak 都满足,&local 报 E0597);任务内部的借用不受限制。

Rust tokio spawn 生命周期 真实验证 动画演示
Rust 内部机制 2026-10-02

select! 取消竞争

下载 tokio 验证 select! 的取消语义:失败的分支被 drop;取消不安全的 Future 会丢消息(通道里剩 [2, 3]);把取走与处理分开才安全;默认随机选择(4910:5090)对 biased 的 10000:0;timeout 超时时内部 Future 被 drop。

Rust tokio select 取消安全 真实验证 动画演示
Rust 内部机制 2026-10-02

异步 Channel

下载 tokio 验证四种异步通道:有界 mpsc 满了 send().await 挂起(背压);无界 mpsc 10 万条 15 ms 发完、积压 100000 条;oneshot 的 drop 语义;broadcast 的 Lagged(4);watch 只保留最新值(v1、v2 被跳过)。

Rust tokio 异步通道 mpsc 真实验证 动画演示
Rust 内部机制 2026-10-02

异步 Mutex 的使用边界

下载 tokio 验证异步里的 Mutex 边界:std MutexGuard 跨 await 让 Future 不是 Send(编译器指出 used across an await);tokio::sync::Mutex 可跨 await;guard 不跨 await 时 std Mutex 可用;单线程运行时里跨 await 持 std 锁会死锁(6 秒不退出);无 await 的短临界区 std 75.5 ms 对 tokio 389.7 ms。

Rust tokio Mutex 异步 死锁 真实验证 动画演示
Rust 内部机制 2026-10-02

阻塞代码混入异步任务

下载 tokio 验证阻塞代码混入异步:4 个工作线程时,k = 3 个阻塞任务时 sleep(10 ms) 只晚几毫秒,k = 4 时晚约 260 ms(线程全被占满);spawn_blocking 晚 3 ms;block_in_place 晚 5 ms 但在 current_thread 里 panic;纯 CPU 计算占满 4 线程时 sleep(10 ms) 用了 178 ms。

Rust tokio 阻塞 spawn_blocking 真实验证 动画演示
Rust 内部机制 2026-10-02

Future 取消与 Drop

tokio 验证 Future 取消:drop JoinHandle 不取消、abort() 才取消;abort 只在 await 点生效(同步循环要跑完);取消不回滚副作用(转账丢 40)而「先 await 后一次性修改」安全;tokio Mutex 的 guard 随 Future 释放;Drop 里不能 await(E0728)。

Rust Future 取消 drop tokio 真实验证 动画演示
Rust 内部机制 2026-10-02

Pin 与 Unpin

用真实运行验证 Pin 与 Unpin:自引用结构体被移动后 ptr 指向旧地址;Pin<Box<T>> 移动两次后数据地址不变;!Unpin 类型拿不到 &mut(get_mut / Pin::new 报 E0277);逐个检查 Unpin(普通类型是,PhantomPinned 与所有 async 块不是);pin! 宏固定在栈上并 poll 出 Ready(6)。

Rust Pin Unpin 自引用 真实验证 动画演示
Rust 内部机制 2026-10-02

Waker 唤醒机制

用带计数的 vtable 验证 Waker:16 字节(数据指针 + vtable);clone / wake_by_ref / wake / drop 各调用哪个函数(wake 消耗 waker 所以不再 drop);Context 里的 &Waker 要 clone 才能保存;will_wake 的结果;忘了调用 wake 时任务永远睡下去。

Rust Waker 异步 唤醒机制 真实验证 动画演示
Rust 内部机制 2026-10-02

自定义 Future

自己写 Timer Future(共享状态 + 保存 waker + 后台线程唤醒)和 join2 组合子:Timer 等 100 ms poll 2 次;顺序 await 两个 100 ms 耗时约 200 ms 而 join2 约 100 ms;不保存 waker 会永远睡着;waker 会随 poll 变化必须每次更新。

Rust 自定义Future Timer join 真实验证 动画演示
京ICP备2026067502号-1京公网安备11010502063487号