gpt4 book ai didi

multithreading - Rust 中使用的 "await"是什么意思?

转载 作者:行者123 更新时间:2023-12-03 11:30:14 25 4
gpt4 key购买 nike

这个问题在某种程度上可能与异步编程有关,而不是与 Rust 有关。但是在谷歌搜索了很多之后,我认为仍然缺少一些要点。因为我正在学习 Rust,所以我会用 Rust 的方式来表达。

先说说我对异步编程的理解---毕竟这是基础,也许我错了也好:

要使程序高效运行,并发处理任务是必不可少的。然后使用线程,只要需要来自线程的数据,就可以加入线程。但是线程不足以像服务器那样处理许多任务。那么线程池就用上了,但是在不知道等待哪个线程的情况下,如何在需要的时候去取数据呢?然后回调函数(简称cb)出现。有了cb,只需要考虑cb中需要做的事情。另外,为了让cpu的开销小,green thread就上来了。

但是如果asyn-waiting的事情需要一个接一个做,导致“回调 hell ”怎么办?好的,“future/promise”风格出现了,它让代码看起来像同步代码,或者可能像一个链(就像在 javascript 中)。但是代码看起来还是不太好。最后,“async/await”风格出现了,作为“future/promise”风格的另一种语法糖。通常,绿色线程风格的“async/await”被称为“协程”,无论是只使用一个 native 线程还是使用多个 native 线程来完成异步任务。

=============================================

据我所知,as关键字“await”只能在“async”函数的范围内使用,并且只能“等待”“async”函数。但为什么?既然已经有了“异步”,它有什么用?无论如何,我测试了下面的代码:

use async_std::{task};


// async fn easy_task() {
// for i in 0..100 {
// dbg!(i);
// }
// println!("finished easy task");
// }

async fn heavy_task(cnt1: i32, cnt2: i32) {
for i in 0..cnt1 {
println!("heavy_task1 cnt:{}", i);
}

println!("heavy task: waiting sub task");
// normal_sub_task(cnt2);
sub_task(cnt2).await;
println!("heavy task: sub task finished");

for i in 0..cnt1 {
println!("heavy_task2 cnt:{}", i);
}
println!("finished heavy task");
}

fn normal_sub_task(cnt: i32) {
println!("normal sub_task: start sub task");
for i in 0..cnt {
println!("normal sub task cnt:{}", i);
}
println!("normal sub_task: finished sub task");
}

async fn sub_task(cnt: i32) {
println!("sub_task: start sub task");
for i in 0..cnt {
println!("sub task cnt:{}", i);
}
println!("sub_task: finished sub task");
}

fn outer_task(cnt: i32) {
for i in 0..cnt {
println!("outer task cnt:{}", i);
}
println!("finished outer task");
}

fn main() {
// let _easy_f = easy_task();
let heavy_f = heavy_task(3000, 500);
let handle = task::spawn(heavy_f);
print!("=================after spawn==============");
outer_task(5000);

// task::join_handle(handle);
task::block_on(handle);
}

我测试得到的结论是:

1.无论等待async sub_task还是在async heavy_task()中间执行normal_sub_task(sync version),下面的代码(heavy loop task2)都不会插队。

2.无论等待async sub_task还是在async heavy_task()中间执行normal_sub_task(同步版本),outer_task有时会插队,打断heavy_task1或async_sub_task/normal_sub_task。

所以,“await”是什么意思,这里好像只用了“asyc”这个关键字。

引用:

asyc_std

sing_dance_example from rust asyncbook

module Task in official rust module

recommended article of rust this week about async-programming

another article about rust thread and async-programming using future crates

stackoverflow question:What is the purpose of async/await in Rust?我得到的结论 2 似乎违反了 Shepmaster 所说的,“...我们认为异步函数应该与第一个等待同步运行。”

最佳答案

await 关键字暂停异步函数的执行,直到等待的 future (future.await) 产生一个值。

这与使用 await 概念的所有其他语言的含义相同。

当等待 future 时,async 函数的“执行状态”被保存到内部执行上下文和其他异步函数在准备好运行时有机会继续执行。

当等待的 future 完成时,异步函数会在准确的暂停点恢复。

如果您认为我只需要 async 并编写如下内容:

// OK: let result = future.await
let result = future

您得到的不是值(value),而是代表 future 值(value)的东西。

如果你标记async一个函数而不等待任何内部您注入(inject)异步引擎的函数主体 顺序任务执行时将作为正常函数运行完成,防止异步行为。

关于您的代码的更多评论

可能是对任务概念的误解引起的混淆。

在 Rust 中学习异步时,我发现了 async book非常有用。

本书将任务定义为:

Tasks are the top-level futures that have been submitted to an executor

heavy_task 确实是您示例中的独特任务,因为它是提交给异步的唯一 future 使用 task::block_on 运行时。

例如函数outer_task与异步世界无关: 这不是一个任务,它会在调用时立即执行。

heavy_task 行为异步并等待sub_task(cnt2) future ... 但 sub_task future 一旦执行 立即完成。

因此,就目前而言,您的代码实际上是按顺序运行的。

但请记住,现实中的事情更加微妙,因为在其他异步任务的存在下await inside heavy_task 用作暂停点并为其他人提供机会要完成的任务。

关于multithreading - Rust 中使用的 "await"是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60239171/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com