You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tokio中tokio::time::sleep是否会引发Rust程序死锁?

问题分析与解决方案

问题根源

你遇到的并非tokio::time::sleep导致的死锁,核心原因是在Tokio异步任务中调用了同步阻塞的Eventador订阅接收方法,耗尽了Tokio Runtime的工作线程,导致剩余任务无法被调度执行。

Tokio默认的工作线程数等于CPU核心数(例如8核CPU对应8个工作线程)。当你启动超过该数量的订阅者任务时,每个任务一开始就调用subscription.recv()——这是一个同步阻塞方法,会直接占用一个工作线程直到收到事件。当工作线程被全部占满后,剩下的任务(比如第9、10个订阅者)根本没有机会被调度,永远卡在等待执行的状态,既无法接收事件,也不会主动退出,最终导致程序无法终止。

解决方案

方案一:使用Eventador异步订阅API(推荐)

Eventador提供了原生异步的订阅接口,替换同步的subscribe为subscribe_async,并使用异步的recv方法,彻底避免阻塞Tokio工作线程:

pub async fn start(self) {
    // 替换为异步订阅
    let mut subscription = self.eventbus.subscribe_async::<Event>().await.unwrap();
    // 异步接收事件
    let value = subscription.recv().await.unwrap().value;
    
    println!("pre sleep {} - {}ms since start", self.i, INSTANT.elapsed().as_millis());
    let now = Instant::now();
    sleep(Duration::from_millis(1000)).await;
    println!("{}: {:?} - {}ms - {}ms since start", self.i, value, now.elapsed().as_millis(), INSTANT.elapsed().as_millis());
}

方案二:用spawn_blocking隔离同步阻塞调用

如果因某些原因必须使用同步订阅接口,将recv()的同步阻塞调用包裹在tokio::task::spawn_blocking中,把阻塞操作转移到Tokio专门的阻塞线程池,避免占用核心工作线程:

pub async fn start(self) {
    let subscription = self.eventbus.subscribe::<Event>();
    // 将同步recv操作放到阻塞线程池执行
    let value = tokio::task::spawn_blocking(move || subscription.recv().value)
        .await
        .unwrap();
    
    println!("pre sleep {} - {}ms since start", self.i, INSTANT.elapsed().as_millis());
    let now = Instant::now();
    sleep(Duration::from_millis(1000)).await;
    println!("{}: {:?} - {}ms - {}ms since start", self.i, value, now.elapsed().as_millis(), INSTANT.elapsed().as_millis());
}

生产环境注意事项

针对100个文件的并发处理场景,必须遵守以下原则:

  • 优先使用异步原生API,避免在Tokio工作线程中执行任何同步阻塞操作(包括IO、第三方同步库调用等)。
  • 若必须使用同步接口,一律通过spawn_blocking隔离到阻塞线程池,确保核心工作线程不被占用。
  • 可以根据业务需求调整Tokio阻塞线程池的大小(通过Builder::max_blocking_threads),但这只是辅助手段,核心还是要避免不必要的阻塞。

内容的提问来源于stack exchange,提问作者twilker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 11:09:56