为什么这个 MutexGuard 没有掉线?

Bre*_*dan 8 lifetime rust

The Rust Book 的第 20 章中,构建了一个线程池的示例实现。作业通过单生产者多消费者通道传递给工作人员:每个工作人员都有一个Arc<Mutex<Receiver>>从队列中挑选工作。

工作线程主体的第一个示例如下所示:

loop {
    let job = receiver.lock().unwrap().recv().unwrap();

    println!("Worker {} got a job; executing.", id);

    job();
}
Run Code Online (Sandbox Code Playgroud)

当我看到这个时,我的第一个想法是“但是互斥锁在job运行时被保持”(即我不希望互斥锁被释放,直到lock循环结束时的返回值超出范围)。

然而,这本书提供了第二个例子:

while let Ok(job) = receiver.lock().unwrap().recv() {
    println!("Worker {} got a job; executing.", id);

    job();
}
Run Code Online (Sandbox Code Playgroud)

这本书说这个例子展示了我描述的问题,即“锁在调用期间保持保持job()”。它继续说,前一个例子逃避了这个问题,因为“一旦语句结束,MutexGuardlock方法返回的值就会被删除let job”。

最后一部分听起来好像,因为MutexGuard从来没有真正分配给变量,一旦表达式完成评估,它的生命周期就结束了。那是有道理的。但第二个例子不也是如此吗?为什么在while表达式中会改变MutexGuard值的生命周期?

use*_*968 6

迈克尔的回答基本上是正确的。更多细节可以在Rust 的关于 Place Expressions, Value Expressions 和 Temporary Lifetimes 的参考资料中找到:

在第一个示例 ( let job = ...) 中,MutexGuard是临时的。临时生命周期在语句结束时结束。因此,MutexGuardlet job = ...语句之后删除了。

在第二个示例中while let ...MutexGuard是 -表达式的检查对象的一部分while。这使得MutexGuard位置表达式上下文中的值表达式的一部分。由于'static无法升级到 a ,整个生命周期scrutinee是封闭块,而不是封闭语句。也就是说,MutexGuard为整个while let-block持有。

  • 对我来说,Rust 为什么会这样工作并不明显。这是人们使用的功能还是只是偶然? (2认同)

Mic*_*son 5

临时变量在语句的结尾处被清除,而不是在表达式的结尾处。

在这种情况下,整个 while 块是语句,而不仅仅是let模式匹配中的表达式。