From 1e10b404237d8bf0ad856ff3faff4b070901c9ae Mon Sep 17 00:00:00 2001 From: KaiserY Date: Tue, 5 Nov 2024 19:32:45 +0800 Subject: [PATCH] update ch17-03 --- src/ch17-03-more-futures.md | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index d9539f1..f75a156 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -247,7 +247,7 @@ received 'you' -我们可以使用 `trpl::join!` 来 await 它们,因为它允许你传递多个 future 类型并产生一个这些类型的元组。我们 *不能* 使用 `trpl::join_all`,因为它要求传递的 future 都拥有相同的类型。请记住,那个错误正式我们开启 `Pin` 探索之旅的原因! +我们可以使用 `trpl::join!` 来 await 它们,因为它允许你传递多个 future 类型并产生一个这些类型的元组。我们 *不能* 使用 `trpl::join_all`,因为它要求传递的 future 都拥有相同的类型。请记住,那个错误正是我们开启 `Pin` 探索之旅的原因! 这是一个基础的权衡取舍:要么我们可以使用 `join_all` 处理动态数量的 future,只要它们都有相同的类型;要么我们可以使用 `join` 函数或者 `join!` 宏来处理固定数量的 future,哪怕它们有着不同的类型。不过这与 Rust 处理任何其它类型是一样的。Future 并不特殊,即便我们采用了一些友好的语法来处理它们,而这其实是好事。 @@ -271,9 +271,31 @@ received 'you' 请注意如果你反转 `race` 参数的顺序,“started” 消息的顺序会改变,即使 `fast` future 总是第一个结束。这是因为这个特定的 `race` 函数实现并不是公平的。它总是以传递的参数的顺序来运行传递的 futures。其它的实现 *是* 公平的,并且会随机选择首先轮询的 future。不过无论我们使用的 race 实现是否公平,其中 *一个* future 会在另一个任务开始之前一直运行到异步代码块中第一个 `await` 为止。 -回忆一下[第一个异步程序][async-program]中提到在每一个 await point,如果被 await 的 future 还没有就绪,Rust 会给运行时一个机会来暂停该任务并切换到另一个。这反过来也是正确的:Rust *只会* 在一个 await point 暂停异步代码块并将控制权交还给运行时。await points 之间的一切都是同步。 +回忆一下[第一个异步程序][async-program]中提到在每一个 await point,如果被 await 的 future 还没有就绪,Rust 会给运行时一个机会来暂停该任务并切换到另一个任务。反过来也是正确的:Rust *只会* 在一个 await point 暂停异步代码块并将控制权交还给运行时。await points 之间的一切都是同步。 -这意味着如果你在异步代码块中做了一堆工作而没有一个 await point,则那个 future 会阻塞其它任何 future 继续进行。 +这意味着如果你在异步代码块中做了一堆工作而没有一个 await point,则那个 future 会阻塞其它任何 future 继续进行。有时你可能会听说这称为一个 future *starving* 其它 future。在一些情况中,这可能不是什么大问题。不过,如果你在进行某种昂贵的设置或者上时间运行的任务,亦或有一个 future 会无限持续运行某些特定任务的话,你会需要思考在何时何地将控制权交还运行时。 + +同样地,如果你有长时间运行的阻塞操作,异步可能是一个提供了将程序的不同部分相互关联起来的实用工具。 + +不过在这种情况下 *如何* 将控制权交还运行时呢? + +### Yielding + +让我们模拟一个长时间运行的操作。示例 17-22 引入了一个 `slow` 函数。它使用 `std::thread::sleep` 而不是 `trpl::sleep` 因此 `slow` 调用会阻塞当前线程若干毫秒。我们可以用 `slow` 来代表现实世界中的长时间运行并阻塞的操作。 + +
+ +文件名:src/main.rs + +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-22/src/main.rs:slow}} +``` + +
示例 17-22:使用 `thread::sleep` 来模拟缓慢的操作
+ +
+ +在示例 17-22 中,我们使用 `slow` 在几个 future 中模拟这类 CPU 密集型工作。首先 [collections]: ch08-01-vectors.html#using-an-enum-to-store-multiple-types [dyn]: ch12-03-improving-error-handling-and-modularity.html