diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index cda2a87..d58b7c5 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -5,7 +5,7 @@ 在这一部分,我们将使用异步来应对一些与第十六章中通过线程解决的相同的并发问题。因为之前我们已经讨论了很多关键理念了,这一部分我们会专注于线程与 future 的区别。 -在很多情况下,使用异步处理并发的 API 与使用线程的非常相似。在其它的一些情况,它们则非常不同。即便线程与异步的的 API *看起来* 很类似,通常它们有着不同的行为,同时它们几乎总是有着不同的性能特点。 +在很多情况下,使用异步处理并发的 API 与使用线程的非常相似。在其它的一些情况,它们则非常不同。即便线程与异步的 API *看起来* 很类似,通常它们有着不同的行为,同时它们几乎总是有着不同的性能特点。 ### 计数 @@ -175,7 +175,7 @@ hi number 9 from the first task! 在示例 16-10 中,我们使用了 `for` 循环来处理从异步信道接收的所有消息。然而,Rust 目前还没有在 *异步* 序列上编写 `for` 循环的方法。取而代之的是,我们需要一个我们还没有见过的新循环类型,即 `while let` 条件循环。`while let` 循环是我们在第六章中见过的 `if let` 结构的循环版本。只要其指定的模式持续匹配循环就会一直执行。 -`rx.recv` 调用产生一个 `Future`,我们会 await 它。运行时会暂停 `Future` 直到它就绪。一旦消息到达,future 会解析为 `Some(message)`,每次消息到达时都会如此。。当信道关闭时,不管是否有 *任何* 消息到达,future 都会解析为 `None` 来表明没有更多的值了,我们也就应该停止轮询,也就是停止等待。 +`rx.recv` 调用产生一个 `Future`,我们会 await 它。运行时会暂停 `Future` 直到它就绪。一旦消息到达,future 会解析为 `Some(message)`,每次消息到达时都会如此。当信道关闭时,不管是否有 *任何* 消息到达,future 都会解析为 `None` 来表明没有更多的值了,我们也就应该停止轮询,也就是停止等待。 `while let` 循环将上述逻辑整合在一起。如果 `rx.recv().await` 调用的结果是 `Some(message)`,我们会得到消息并可以在循环体中使用它,就像使用 `if let` 一样。如果结果是 `None`,则循环停止。每次循环执行完毕,它会再次触发 await point,如此运行时会再次暂停直到另一条消息到达。 diff --git a/src/ch17-05-traits-for-async.md b/src/ch17-05-traits-for-async.md index 5564d39..f69fbcb 100644 --- a/src/ch17-05-traits-for-async.md +++ b/src/ch17-05-traits-for-async.md @@ -183,9 +183,9 @@ pub trait Future { `Unpin` 是一个标记 trait(marker trait),类似于我们在第十六章见过的 `Send` 和 `Sync` trait,因此它们自身没有功能。标记 trait 的存在只是为了告诉编译器在给定上下文中可以安全地使用实现了给定 trait 的类型。`Unpin` 告知编译器这个给定类型**无需**维护被提及的值是否可以安全地移动的任何保证。 -正如 `Send` 和 `Sync` 一样,编译器自动为所有被证明为安全的类型实现 `Unpin`。同样类似于 `Send` 和 `Sync`,有一个特殊的例子**不会**为类型实现 `Unpin`。这个例子的符号是 impl !Unpin for SomeType,这里 SomeType 是一个当指向它的指针被用于 `Pin` 时**必须**维护安全保证的类型的名字。 +正如 `Send` 和 `Sync` 一样,编译器自动为所有被证明为安全的类型实现 `Unpin`。同样类似于 `Send` 和 `Sync`,有一个特殊的例子**不会**为类型实现 `Unpin`。这个例子的符号是 impl !Unpin for SomeType,这里 SomeType 指的是这样的一种类型:为了确保内存安全,当一个指向它的指针被用于 `Pin` 时,无论何时它都**必须**维护其不被移动的安全保证。 -换句话说,关于 `Pin` 与 `Unpin` 的关系有两点需要牢记。首先,`Unpin` 用于 “正常” 情况,而 `!Unpin` 用于特殊情况。其次,一个类型是否实现了 `Unpin` 或 `!Unpin` **只在于**你是否使用了一个被 pin 住的指向类似 Pin<&mut SomeType> 类型的指针。 +换句话说,关于 `Pin` 与 `Unpin` 的关系有两点需要牢记。首先,`Unpin` 用于 “正常” 情况,而 `!Unpin` 用于特殊情况。其次,不管一个类型是实现了 `Unpin` 或者实现了 `!Unpin`,它**只在**你使用了一个被 pin 住的指向类似 Pin<&mut SomeType> 类型的指针时才会产生影响。 更具体地说,考虑一下 `String`:它包含一个长度和构成它的 Unicode 字符。我们可以将 `String` 封装进 `Pin` 中,如图 17-8 所示。然而,就像 Rust 中大部分其它类型一样,`String` 自动实现了 `Unpin`。 @@ -197,7 +197,7 @@ pub trait Future { -因此,如果 `String` 实现了 `!Unpin` 我们可以做一些非法的事,比如像图 17-9 这样在完全相同的内存位置将一个字符串替换为另一个字符串。这并不违反 `Pin` 的规则,因为 `String` 没有内部引用这使得它可以安全地移动!这是为何它实现了 `Unpin` 而不是 `!Unpin`。 +因此,对于 `String` 来说,我们可以像图 17-9 这样在完全相同的内存位置将一个字符串替换为另一个字符串,而如果 `String` 实现的是 `!Unpin`,这个操作本该是非法的。这并不违反 `Pin` 的规则,因为 `String` 没有内部引用这使得它可以安全地移动!这是为何它实现了 `Unpin` 而不是 `!Unpin`。