热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

异步Rust中的多线程为何无法实现并行化?

探讨异步Rust中多线程代码无法实现并行化的原因及解决方案。

我尝试通过运行以下函数来有意耗尽 API 限制(900 次调用):

#[get("/exhaust")]
pub async fn exhaust(_pool: web::Data, config: web::Data>) -> impl Responder {
let mut handles = vec![];
for i in 1..900 {
let inner_cOnfig= config.clone();
let handle = thread::spawn(move || async move {
println!("running thread {}", i);
get_single_tweet(inner_config.as_ref().deref(), "1401287393228038149")
.await
.unwrap();
});
handles.push(handle);
}
for h in handles {
h.join().unwrap().await;
}
HttpResponse::Ok()
}

我的机器有 16 个内核,所以我希望上述代码的运行速度比单线程函数快 16 倍,但实际上它与单线程版本一样慢。

为什么会这样?我遗漏了什么?

注意:这move || async move部分对我来说看起来有些奇怪,但我是按照编译器的建议这样做的。由于async closures being unstable,这可能是问题所在吗?

解答

此代码确实会async同步运行您的块。一个async块创建了一个实现Future类型的对象,但需要注意的是,Future不会自动开始运行,它们必须被await或提供给执行器才能运行。

thread::spawn使用返回Future的闭包调用并不会执行这些Future;线程只是创建async块并返回。因此,这些async块实际上并未被执行,直到你在循环中await它们,这将按顺序处理这些Future

解决此问题的一种方法是使用join_allfutures库中同时运行它们。

let mut futs = vec![];
for i in 1..900 {
let inner_cOnfig= config.clone();
futs.push(async move {
println!("running thread {}", i);
get_single_tweet(inner_config.as_ref().deref(), "1401287393228038149")
.await
.unwrap();
});
}
futures::future::join_all(futs).await;

通过这种方式,所有Future将并行执行,从而实现真正的并行化。


推荐阅读
author-avatar
再生Solo_868
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有