From 4a1fdc6d3957a116d96fff9c0e203d31a1b253be Mon Sep 17 00:00:00 2001 From: Unisko PENG Date: Thu, 6 Apr 2023 14:36:45 +0800 Subject: [PATCH] Update Ch20 --- ...ect_Building_a_Multithreaded_Web_Server.md | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/Ch20_Final_Project_Building_a_Multithreaded_Web_Server.md b/src/Ch20_Final_Project_Building_a_Multithreaded_Web_Server.md index 549a33a..6b61c60 100644 --- a/src/Ch20_Final_Project_Building_a_Multithreaded_Web_Server.md +++ b/src/Ch20_Final_Project_Building_a_Multithreaded_Web_Server.md @@ -1139,8 +1139,28 @@ Worker 1 获取到一项作业;执行中。 > 注意:若咱们在多个窗口同时打开 `/sleep`,他们可能会在设置的时间间隔每次加载一个。有些 web 浏览器会出于缓存原因,而顺序执行同一请求的多个实例。这样的局限并不是由咱们的服务器导致的。 +在了解了第 18 章中的 `while let` 循环后,咱们可能想知道,为何咱们没有如下清单 20-21 中所示的那样,编写 `worker` 线程的代码。 +文件名:`src/lib.rs` -这段代码将会编译及运行,但不会产生所需的线程行为:慢速请求仍将导致别的请求等待被处理。至于原因则有点微妙:由于锁的所有权是基于 `lock` 方法返回的 `LockResult>` 中,`MutexGuard` 的生命周期,因此这个 `Mutex` 结构体没有公开的 `unlock` 方法。在编译时,借用检查器可于随后,就除非咱们拿着 `Mutex` 所守卫的某项资源的锁,否则无法访问该项资源这一规矩强制加以检查。但是,若咱们没有注意到 `MutexGuard` 的生命周期,那么这样的实现同样能导致锁相较预期被占用更长时间。 +```rust +impl Worker { + fn new(id: usize, receiver: Arc>>) -> Worker { + let thread = thread::spawn(move || { + while let Ok(job) = receiver.lock().unwrap().recv() { + println! ("Worker {id} 获取到一项作业;执行中。"); -由于在 `let` 之下,等号右侧的表达式中用到的任何临时值,都会在 `let` 语句结束时被立即丢弃,因此使用了 `let job = receiver.lock().unwrap().recv().unwrap();` 的清单 20-20 中代码是工作的。但是,`while let`(以及 `if let` 与 `match`) 则是在相关代码块结束前,不会丢弃那些临时值。在清单 20-21 中, + job(); + } + }); + + Worker { id, thread } + } +} +``` + +*清单 20-21:使用 `while let` 的一种 `Worker::new` 替代实现* + +这段代码将会编译及运行,但不会产生所需的线程行为:慢速请求仍将导致别的请求等待被处理。至于原因则有点微妙:由于锁的所有权是基于 `lock` 方法返回的 `LockResult>` 中,`MutexGuard` 的生命周期,因此这个 `Mutex` 结构体没有公开的 `unlock` 方法。在编译时,借用检查器可于随后,就除非咱们拿着 `Mutex` 所守卫的某项资源的锁,否则无法访问该项资源这一规则强制加以检查。但是,若咱们没有注意到 `MutexGuard` 的生命周期,那么这样的实现同样能导致锁相较预期被占用更长时间。 + +由于在 `let` 之下,等号右侧的表达式中用到的任何临时值,都会在 `let` 语句结束时被立即丢弃,因此使用了 `let job = receiver.lock().unwrap().recv().unwrap();` 的清单 20-20 中代码是工作的。但是,`while let`(以及 `if let` 与 `match`) 则是在相关代码块结束前,不会丢弃那些临时值。在清单 20-21 中,锁会在到 `job()` 的调用其将保持被持有,这意味着别的 `worker` 就没法收到作业。