与Mutex
一起工作时,我遇到了这种僵局情况
包含Mutex
类型的字段的结构如下:
struct MyStruct {
inner_map: Arc<Mutex<HashMap<i32, Vec<i32>>>>,
}
我已经通过互斥锁访问了此内部地图:
impl MyStruct {
fn test_lock(&self, key: &i32) {
let my_option = self.inner_map.lock().unwrap().remove(key);
if let Some(my_vec) = my_option {
for _inner_val in my_vec {
self.inner_map.lock().unwrap();
println!("Passed test_lock1");
}
}
}
}
这很好,没有死锁,因为我从HashMap
中删除了值,并从HashMap
中获得了所有权
与test_lock非常相似的函数,仅具有区别,而不是将my_option
变量声明为已删除的值,而在if let
调用中使用了它,并且 在这种情况下会导致死锁 :
impl MyStruct{
// Why this function goes to deadlock since remove gets the ownership of the data?
fn test_lock2(&self, key: &i32) {
if let Some(my_vec) = self.inner_map.lock().unwrap().remove(key) {
for _inner_val in my_vec {
self.inner_map.lock().unwrap();
println!("Passed test_lock2");
}
}
}
}
声明变量会改变这种行为的主要原因是什么?
答案 0 :(得分:8)
The lock is released when the LockResult
goes out of scope。
现在我们必须深入scope rules regarding this temporary value。
临时值的范围是封闭语句。
在第一个代码段中,这意味着锁在进入if / let构造之前超出范围。没有僵局。
但是var mat_type = (globalData.Material.Mat_type);
var picture = (globalData.Material[mat_type].picture);
条件下的临时值的范围是整个if / let构造:
临时值的寿命通常是
- 最里面的语句;块的尾部表达式是 被视为包围该语句的语句的一部分,或者
- 条件表达式或循环条件表达式,如果 在if 的条件表达式中或在 循环while表达式的条件表达式。
但是,当创建分配给let声明的临时值表达式时,将使用封闭块的生存期来创建临时值表达式,因为使用封闭的let声明将确保出现错误(因为指向的指针临时文件将存储到变量中,但在使用该变量之前将其释放)
在第二个片段中,锁的范围因此覆盖了整个if / let构造。
这说明了当您尝试再次锁定循环时为什么第一个锁仍然处于活动状态。