Rust使用Tokio的join宏实现异步并发时运行时长异常问题
问题原因
核心问题是使用了标准库的阻塞睡眠std::thread::sleep,没有使用Tokio提供的异步睡眠API。
Tokio的异步调度是协作式的,需要任务主动通过.await让出线程执行权才能切换任务。std::thread::sleep会直接阻塞当前运行异步任务的工作线程,线程被占用期间无法切换执行另一个异步函数,因此两个函数的睡眠操作会串行执行,总耗时叠加为4秒。
修正方案
替换异步函数中的睡眠实现,使用Tokio的异步sleep并添加.await让出执行权,现有Cargo.toml配置无需修改,已通过full特性引入了time相关依赖。
修正后的Rust代码:
use tokio::join; use tokio::time::sleep; // 替换为tokio异步sleep use std::time::{Duration, Instant}; async fn fn_1() -> i8 { sleep(Duration::from_secs(2)).await; // 异步sleep需要await主动让出执行权 2 } async fn fn_2() -> i8 { sleep(Duration::from_secs(2)).await; 1 } #[tokio::main] async fn main() { let now = Instant::now(); println!("start: {:#?}", now.elapsed()); let a = fn_1(); let b = fn_2(); join!(a, b); println!("end: {:#?}", now.elapsed()); }
运行结果
修改后执行程序,总耗时约为2秒,符合预期:
start: 32ns end: 2.00124789s
注意事项
- 异步函数中所有阻塞类操作都需要替换为对应异步运行时提供的异步实现,除睡眠外,文件IO、网络IO、计算密集型逻辑都要遵循该规则,避免阻塞工作线程导致并发失效
join!宏仅负责等待多个Future执行完成,Future本身需要内部存在.await等让出执行权的逻辑,才能实现并发调度
内容的提问来源于stack exchange,提问作者miravelardo
相关产品推荐
相关产品推荐

