< 返回版块

LCW-QAQ 发表于 2021-12-14 16:13

Tags:async,async_std,coroutines

第一次接触协程, 一个线程可以开辟多个协程,这些协程由runtime并发执行。 协程运行在一个线程中,为什么下面的代码打印的线程是不同的。

use std::time::{Duration, Instant};
use async_std::{
    task::{sleep, spawn}
};
use futures::future::{join_all};

#[async_std::main]
async fn main() {
    let mut vec = Vec::new();
    let now = Instant::now();
    for i in 0..100 {
        vec.push(spawn(async move {
            sleep(Duration::from_secs(1)).await;
            println!("CountDown {} (on {:?})", i, std::thread::current());
        }));
    }
    join_all(vec).await;
    println!("{:?}", now.elapsed());
}

运行结果

CountDown 0 (on Thread { id: ThreadId(2), name: Some("async-std/runtime"), .. })

CountDown 98 (on Thread { id: ThreadId(7), name: Some("async-std/runtime"), .. })

CountDown 49 (on Thread { id: ThreadId(4), name: Some("async-std/runtime"), .. })

CountDown 1 (on Thread { id: ThreadId(2), name: Some("async-std/runtime"), .. })

CountDown 60 (on Thread { id: ThreadId(7), name: Some("async-std/runtime"), .. })

CountDown 64 (on Thread { id: ThreadId(8), name: Some("async-std/runtime"), .. }

......

评论区

写评论
kwsc98 2024-04-26 19:01

这个代码的意思其实是,把任务丢到异步线程池中执行。想要顺序打印,就直接.await。而且tokio不保证由同一个线程去执行.await。不过你这种方法内没有阻塞的操作,一般tokio还是会再同一个线程内调度的

Bai-Jinlin 2021-12-17 12:49

有一些thread pre core的runtime,比如字节跳动的monoio什么的

--
👇
宁: 可以禁止协程切换线程吗 runtime有多个线程,但每个task只在一个线程里运行,禁止切换到其他线程

--
👇
Aya0wind: 一个线程可以开辟多个协程,但是没有说一个协程一直只能在一个线程里运行,也没说runtime只能用一个线程来运行创建的协程。
事实上现在rust主流的runtime,默认都是有一个线程池,创建一个协程,runtime会把他投递到不同的线程里运行,并且像tokio这种带任务窃取的,会把其他线程的协程任务拿过来执行,这样你一个异步函数中await前和后的代码可能都会运行在不同的线程里。
当然tokio也提供了单线程的runtime,创建一个只使用一个线程的runtime来运行异步函数,就保证在一个线程里了。

Aya0wind 2021-12-17 10:17

可以,actix的runtime就是这样搞的,可以去看它的实现,简单来说就是创建多个单线程runtime,然后把task分配给其中一个执行,之后不再移动,给谁就由谁执行完。

--
👇
宁: 可以禁止协程切换线程吗 runtime有多个线程,但每个task只在一个线程里运行,禁止切换到其他线程

--
👇
Aya0wind: 一个线程可以开辟多个协程,但是没有说一个协程一直只能在一个线程里运行,也没说runtime只能用一个线程来运行创建的协程。
事实上现在rust主流的runtime,默认都是有一个线程池,创建一个协程,runtime会把他投递到不同的线程里运行,并且像tokio这种带任务窃取的,会把其他线程的协程任务拿过来执行,这样你一个异步函数中await前和后的代码可能都会运行在不同的线程里。
当然tokio也提供了单线程的runtime,创建一个只使用一个线程的runtime来运行异步函数,就保证在一个线程里了。

Simon 2021-12-15 13:59

可以禁止协程切换线程吗 runtime有多个线程,但每个task只在一个线程里运行,禁止切换到其他线程

--
👇
Aya0wind: 一个线程可以开辟多个协程,但是没有说一个协程一直只能在一个线程里运行,也没说runtime只能用一个线程来运行创建的协程。
事实上现在rust主流的runtime,默认都是有一个线程池,创建一个协程,runtime会把他投递到不同的线程里运行,并且像tokio这种带任务窃取的,会把其他线程的协程任务拿过来执行,这样你一个异步函数中await前和后的代码可能都会运行在不同的线程里。
当然tokio也提供了单线程的runtime,创建一个只使用一个线程的runtime来运行异步函数,就保证在一个线程里了。

作者 LCW-QAQ 2021-12-14 23:43

感谢Bai-Jinlin Aya0wind, 明白了

Aya0wind 2021-12-14 19:36

一个线程可以开辟多个协程,但是没有说一个协程一直只能在一个线程里运行,也没说runtime只能用一个线程来运行创建的协程。
事实上现在rust主流的runtime,默认都是有一个线程池,创建一个协程,runtime会把他投递到不同的线程里运行,并且像tokio这种带任务窃取的,会把其他线程的协程任务拿过来执行,这样你一个异步函数中await前和后的代码可能都会运行在不同的线程里。
当然tokio也提供了单线程的runtime,创建一个只使用一个线程的runtime来运行异步函数,就保证在一个线程里了。

Bai-Jinlin 2021-12-14 16:45

因为你这async_std的默认的执行器是以多线程模式创建的。

1 共 7 条评论, 1 页