[英]Why does variable binding affect lifetime inside a loop body?
In "The Rust Programming Language" in chapter 20 you go through an exercise of building a simple multi-threaded web server. 在第20章的 “ Rust编程语言”中,您将练习构建一个简单的多线程Web服务器。 In the exercise you use a single std::sync::mpsc
channel. 在练习中,您使用单个std::sync::mpsc
通道。 The worker threads all access a single Receiver which is contained like: Arc<Mutex<mpsc::Receiver<Message>>>
. 所有工作线程都访问一个包含以下内容的单个接收器: Arc<Mutex<mpsc::Receiver<Message>>>
。
If we write the worker thread like: 如果我们将工作线程编写为:
let thread = thread::spawn(move || loop {
match receiver.lock().unwrap().recv().unwrap() {
Message::NewJob(job) => {
println!("Worker {} got a job; executing.", id);
job.call_box();
println!("Worker {} job complete.", id);
}
Message::Terminate => {
println!("Worker {} was told to terminate.", id);
break;
}
};
println!("hello, loop");
});
Then we do not achieve concurrency, apparently the worker holds on to the mutex lock I supposed because no worker is able to pull off another job until the previous one is complete. 然后,我们就无法实现并发性, 显然该工作程序会保留我假定的互斥锁,因为在上一个工作完成之前,任何工作程序都无法完成另一个工作。 However if we simply change it to this (how the book shows the code): 但是,如果我们仅将其更改为(本书显示代码的方式):
let thread = thread::spawn(move || loop {
let message = receiver.lock().unwrap().recv().unwrap();
match message {
Message::NewJob(job) => {
println!("Worker {} got a job; executing.", id);
job.call_box();
println!("Worker {} job complete.", id);
}
Message::Terminate => {
println!("Worker {} was told to terminate.", id);
break;
}
};
println!("hello, loop");
});
Then everything works fine. 然后一切正常。 If you fire off 5 requests you'll see each thread gets one immediately. 如果触发5个请求,您将看到每个线程立即获得一个。 Concurrency! 并发!
The question is "why does variable binding affect lifetime" (I'm assuming that's the reason). 问题是“为什么变量绑定会影响生存期”(我假设这就是原因)。 Or if not then I'm missing something and what is that?! 否则,我会丢失什么,那又是什么? The book itself talks about how you cannot implement the worker loop with while let Ok(job) = receiver.lock().unwrap().recv() {
because of the scope of the lock but apparently even inside the loop there be dragons. 该书本身讨论了如何while let Ok(job) = receiver.lock().unwrap().recv() {
情况下实现工人循环,由于锁的范围,但显然即使在循环内部也有龙。
Because in Rust, "resource acquisition is initialization" . 因为在Rust中, “资源获取是初始化” 。
Specifically receiver.lock()
returns a type which acquires the lock when it is initialized and releases the lock when it is dropped. 具体来说, receiver.lock()
返回一种类型,该类型在初始化时获取锁,并在删除时释放锁。
In your first example, the lifetime of the MutexGuard
extends to the end of the match
statement, so the lock will be held while job.call_box()
is called. 在您的第一个示例中, MutexGuard
的生存期延长至match
语句的末尾,因此在调用job.call_box()
将保留该锁。
match receiver.lock().unwrap().recv().unwrap() {
// ...
};
// `MutexGuard` is dropped and lock is released here
In your second example, the lock guard is only kept alive long enough to read a message from your message queue; 在您的第二个示例中,锁保护仅保持足够长的时间才能从您的消息队列中读取一条消息。 the lock guard is dropped at the end of the statement and the lock is released before the match
is entered. 语句结尾处将放下锁保护,并在输入match
之前释放锁。
let message = receiver.lock().unwrap().recv().unwrap();
// `MutexGuard` is dropped and lock is released here
match message {
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.