Don*_*bin 4 multithreading asynchronous rust async-await
这个问题可能在某种程度上与异步编程相关,而不是 Rust。但是经过大量谷歌搜索后,我认为仍然缺少一些内容。由于我正在学习 Rust,所以我会用 Rust 的方式来表达它。
先说一下我对异步编程的理解---毕竟这是基础,也许我错了也好,没有也好:
为了使程序高效运行,并发处理任务是必不可少的。然后使用线程,只要需要线程中的数据就可以加入该线程。但是线程不足以像服务器那样处理许多任务。那么就使用了线程池,但是在需要数据的时候又不知道哪个线程应该等待的情况下如何取数据呢?然后回调函数(简称cb)出现了。有了cb,只需要考虑cb中需要做的事情。另外,为了让cpu的开销很小,绿色线程就出现了。
但是,如果异步等待的事情需要一个接一个地执行,这会导致“回调地狱”怎么办?好的,“future/promise”风格出现了,它让代码看起来像同步代码,或者可能像一条链(就像在 javascript 中)。但代码看起来仍然不太好。最后,“async/await”风格出现,作为“future/promise”风格的另一种语法糖。通常,具有绿色线程风格的“异步/等待”被称为“协程”,无论是仅使用一个本机线程还是在异步任务上使用多本机线程。
===============================================
据我目前所知,关键字“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);
}
Run Code Online (Sandbox Code Playgroud)
我测试得到的结论是:
1.无论是等待async sub_task还是在async Heavy_task()中间执行normal_sub_task(sync version),下面的代码(重循环task2)都不会插队。
2.无论是等待async sub_task还是在async Heavy_task()中间执行normal_sub_task(sync version),outer_task有时会插队,破坏heavy_task1或async_sub_task/normal_sub_task。
因此,“await”是什么意思,这里似乎只使用了关键字“asyc”。
参考:
来自 rust asyncbook 的 sing_dance_example
另一篇关于 Rust 线程和使用未来板条箱进行异步编程的文章
stackoverflow 问题:Rust 中 async/await 的目的是什么? 我得到的结论 2 似乎违反了 Shepmaster 所说的,“...我们认为异步函数应该与第一个等待同步运行。”
该await关键字暂停异步函数的执行,直到等待的 future ( future.await) 产生一个值。
它与使用await 概念的所有其他语言具有相同的含义。
当等待未来时,函数的“执行状态”async将保留到内部执行上下文中,并且其他异步函数如果准备好运行,则有机会继续进行。
当等待的未来完成时,异步函数将在确切的暂停点恢复。
如果你认为我只需async要写一些类似的东西:
// OK: let result = future.await
let result = future
Run Code Online (Sandbox Code Playgroud)
你得到的不是一个值,而是代表未来准备好的值的东西。
如果您标记async一个函数而不等待函数体内的任何内容,那么您将向异步引擎注入一个顺序任务,该任务在执行时将作为正常函数运行完成,从而防止异步行为。
混乱可能是由于对任务概念的误解而产生的。
当学习 Rust 中的异步时,我发现异步书非常有用。
本书将任务定义为:
任务是已提交给执行者的顶级 future
heavy_task这确实是您的示例中的独特任务,因为它是使用 提交给异步运行时的唯一未来任务task::block_on。
例如,该函数outer_task与异步世界无关:它不是一个任务,它在调用时立即执行。
heavy_task行为异步并等待
sub_task(cnt2)future ...但是sub_taskfuture 一旦执行就会立即完成。
因此,就目前情况而言,您的代码实际上表现为顺序的。
但请记住,现实中的事情更加微妙,因为在存在其他异步任务的情况下,内部
await充当heavy_task暂停点,并为其他任务的执行提供了完成的机会。
| 归档时间: |
|
| 查看次数: |
1734 次 |
| 最近记录: |