为什么这个 MutexGuard 没有被丢弃?
Why is this MutexGuard not dropped?
在Chapter 20 of The Rust Book中,构建了一个线程池的示例实现。作业通过单生产者多消费者通道传递给工人:每个工人都有一个 Arc<Mutex<Receiver>>
来从队列中挑选作业。
工作线程主体的第一个示例如下所示:
loop {
let job = receiver.lock().unwrap().recv().unwrap();
println!("Worker {} got a job; executing.", id);
job();
}
当我看到这个时,我的第一个想法是 "but the mutex is held while job
is run"(即我没想到互斥锁会被释放,直到 lock
的 return 值最后超出范围循环)。
然而这本书提供了第二个例子:
while let Ok(job) = receiver.lock().unwrap().recv() {
println!("Worker {} got a job; executing.", id);
job();
}
书上说这个例子展示了我描述的问题,即"the lock remains held for the duration of the call to job()
"。它继续说前一个例子逃避了这个问题,因为 "the MutexGuard
returned from the lock
method is dropped as soon as the let job
statement ends".
最后一部分听起来好像,因为 MutexGuard
从未实际分配给变量,它的生命周期在表达式完成计算后立即结束。那是有道理的。但是第二个例子不也是如此吗?为什么在 while
表达式中会改变 MutexGuard
值的生命周期?
临时变量在语句末尾被清除,而不是在表达式末尾。
在这种情况下,整个 while 块都是语句,而不仅仅是 let
模式匹配中的表达式。
迈克尔的回答基本上是正确的。可以在 Rust's reference regarding Place Expressions, Value Expressions and Temporary Lifetimes:
中找到更多详细信息
在第一个示例 (let job = ...
) 中,MutexGuard
是临时的。临时生命周期在语句结束时结束。因此 MutexGuard
在 let job = ...
语句之后被删除。
在第二个示例 while let ...
中,MutexGuard
是 while
表达式的 scrutinee 的一部分。这使得 MutexGuard
成为位置表达式上下文中值表达式的一部分。由于无法升级到 'static
,因此整个 scrutinee
的生命周期是封闭块,而不是封闭语句。也就是说,MutexGuard
为整个 while let
块保留。
在Chapter 20 of The Rust Book中,构建了一个线程池的示例实现。作业通过单生产者多消费者通道传递给工人:每个工人都有一个 Arc<Mutex<Receiver>>
来从队列中挑选作业。
工作线程主体的第一个示例如下所示:
loop {
let job = receiver.lock().unwrap().recv().unwrap();
println!("Worker {} got a job; executing.", id);
job();
}
当我看到这个时,我的第一个想法是 "but the mutex is held while job
is run"(即我没想到互斥锁会被释放,直到 lock
的 return 值最后超出范围循环)。
然而这本书提供了第二个例子:
while let Ok(job) = receiver.lock().unwrap().recv() {
println!("Worker {} got a job; executing.", id);
job();
}
书上说这个例子展示了我描述的问题,即"the lock remains held for the duration of the call to job()
"。它继续说前一个例子逃避了这个问题,因为 "the MutexGuard
returned from the lock
method is dropped as soon as the let job
statement ends".
最后一部分听起来好像,因为 MutexGuard
从未实际分配给变量,它的生命周期在表达式完成计算后立即结束。那是有道理的。但是第二个例子不也是如此吗?为什么在 while
表达式中会改变 MutexGuard
值的生命周期?
临时变量在语句末尾被清除,而不是在表达式末尾。
在这种情况下,整个 while 块都是语句,而不仅仅是 let
模式匹配中的表达式。
迈克尔的回答基本上是正确的。可以在 Rust's reference regarding Place Expressions, Value Expressions and Temporary Lifetimes:
中找到更多详细信息在第一个示例 (let job = ...
) 中,MutexGuard
是临时的。临时生命周期在语句结束时结束。因此 MutexGuard
在 let job = ...
语句之后被删除。
在第二个示例 while let ...
中,MutexGuard
是 while
表达式的 scrutinee 的一部分。这使得 MutexGuard
成为位置表达式上下文中值表达式的一部分。由于无法升级到 'static
,因此整个 scrutinee
的生命周期是封闭块,而不是封闭语句。也就是说,MutexGuard
为整个 while let
块保留。