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

为何Tokio单线程模式无法实现并发?代码异常排查

问题:单线程Tokio环境下异步任务无法并发执行?

当我使用flavor = "current_thread"运行以下代码时,仅能看到第一个任务的输出,第二个任务无任何输出。我原本认为即使是单线程执行,异步代码也可以实现并发运行,请问我忽略了什么?

use std::{
    thread,
    time::{Duration, SystemTime},
};

#[tokio::main(flavor = "current_thread")]
async fn main() {
    let handle_1 = tokio::spawn(async move {
        loop {
            println!("{:?} Hello from 1", SystemTime::now());
            thread::sleep(Duration::from_millis(2000))
        }
    });
    let handle_2 = tokio::spawn(async move {
        loop {
            println!("{:?} Hello from 2", SystemTime::now());
            thread::sleep(Duration::from_millis(5000))
        }
    });
    handle_1.await.unwrap();
    handle_2.await.unwrap();
}

输出:

SystemTime { tv_sec: 1719896401, tv_nsec: 253252588 } Hello from 1
SystemTime { tv_sec: 1719896403, tv_nsec: 253411156 } Hello from 1
SystemTime { tv_sec: 1719896405, tv_nsec: 253504834 } Hello from 1
SystemTime { tv_sec: 1719896407, tv_nsec: 253627641 } Hello from 1
SystemTime { tv_sec: 1719896409, tv_nsec: 253785910 } Hello from 1
SystemTime { tv_sec: 1719896411, tv_nsec: 254074102 } Hello from 1
SystemTime { tv_sec: 1719896413, tv_nsec: 254410243 } Hello from 1
SystemTime { tv_sec: 1719896415, tv_nsec: 254574553 } Hello from 1
SystemTime { tv_sec: 1719896417, tv_nsec: 254955748 } Hello from 1
SystemTime { tv_sec: 1719896419, tv_nsec: 258449707 } Hello from 1
SystemTime { tv_sec: 1719896421, tv_nsec: 258703255 } Hello from 1
SystemTime { tv_sec: 1719896423, tv_nsec: 258839315 } Hello from 1
SystemTime { tv_sec: 1719896425, tv_nsec: 259088384 } Hello from 1
SystemTime { tv_sec: 1719896427, tv_nsec: 259232553 } Hello from 1
SystemTime { tv_sec: 1719896429, tv_nsec: 260017836 } Hello from 1

原因分析与解决方案

你忽略了阻塞调用会抢占Tokio单线程运行时的执行权。

Tokio的异步运行时依赖任务主动让出CPU(即"yield")来实现单线程下的并发。而代码中使用的thread::sleep是同步阻塞调用,它会直接让当前线程进入休眠状态,完全占用执行权,Tokio调度器根本没有机会切换到第二个任务执行。

要解决这个问题,必须使用Tokio提供的异步休眠API tokio::time::sleep,它会在休眠期间主动让出CPU,让调度器可以切换到其他任务:

use std::time::{Duration, SystemTime};

#[tokio::main(flavor = "current_thread")]
async fn main() {
    let handle_1 = tokio::spawn(async move {
        loop {
            println!("{:?} Hello from 1", SystemTime::now());
            tokio::time::sleep(Duration::from_millis(2000)).await;
        }
    });
    let handle_2 = tokio::spawn(async move {
        loop {
            println!("{:?} Hello from 2", SystemTime::now());
            tokio::time::sleep(Duration::from_millis(5000)).await;
        }
    });
    handle_1.await.unwrap();
    handle_2.await.unwrap();
}

修改后,两个任务会交替输出:第一个任务每2秒打印一次,第二个任务每5秒打印一次,单线程下的异步并发得以实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 14:22:04