在chapter 20的“ The Rust Programming Language”中,您将练习构建一个简单的多线程Web服务器。在练习中,您使用单个<!-- item template -->
<script type="text/x-template" id="item-template">
<li>
<div
:class="{bold: isFolder}"
@click="toggle"
@dblclick="makeFolder">
{{ item.name }}
<span v-if="isFolder">[{{ isOpen ? '-' : '+' }}]</span>
</div>
<ul v-show="isOpen" v-if="isFolder">
<tree-item
class="item"
v-for="(child, index) in item.children"
:key="index"
:item="child"
@make-folder="$emit('make-folder', $event)"
@add-item="$emit('add-item', $event)"
></tree-item>
<li class="add" @click="$emit('add-item', item)">+</li>
</ul>
</li>
</script>
<p>(You can double click on an item to turn it into a folder.)</p>
<!-- the demo root element -->
<ul id="demo">
<tree-item
class="item"
:item="treeData"
@make-folder="makeFolder"
@add-item="addItem"
></tree-item>
</ul>
var treeData = {
name: 'My Tree',
children: [
{ name: 'hello' },
{ name: 'wat' },
{
name: 'child folder',
children: [
{
name: 'child folder',
children: [
{ name: 'hello' },
{ name: 'wat' }
]
},
{ name: 'hello' },
{ name: 'wat' },
{
name: 'child folder',
children: [
{ name: 'hello' },
{ name: 'wat' }
]
}
]
}
]
}
频道。所有工作线程都访问单个接收器,该接收器包含以下内容:std::sync::mpsc
。
如果我们将工作线程编写为:
Arc<Mutex<mpsc::Receiver<Message>>>
那我们就没有实现并发性,显然工人坚持使用我认为的互斥锁,因为在上一个作业完成之前,没有工人能够拉出另一个作业。但是,如果我们只是简单地将其更改为(书中显示代码的方式):
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");
});
然后一切正常。如果触发5个请求,您将看到每个线程立即获得一个。并发!
问题是“为什么变量绑定会影响生存期”(我假设是原因)。否则,我会丢失什么,那又是什么?该书本身讨论了由于锁定范围的原因,如何无法使用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");
});
实现worker循环,但显然甚至在内部循环中也有龙。
答案 0 :(得分:2)
因为在Rust中,"resource acquisition is initialization"。
具体来说,receiver.lock()
返回一种类型,该类型在初始化时获取锁,而在删除时释放锁。
在您的第一个示例中,MutexGuard
的生存期延长到match
语句的末尾,因此将在调用job.call_box()
时保持锁定。
match receiver.lock().unwrap().recv().unwrap() {
// ...
};
// `MutexGuard` is dropped and lock is released here
在第二个示例中,锁保护仅保持足够长的时间才能从您的消息队列中读取消息;在语句的末尾放下了锁卫,并在输入match
之前释放了锁。
let message = receiver.lock().unwrap().recv().unwrap();
// `MutexGuard` is dropped and lock is released here
match message {