我在使用 Mutex
时遇到过这种死锁情况
包含Mutex
类型字段的结构如下:
struct MyStruct {
inner_map: Arc<Mutex<HashMap<i32, Vec<i32>>>>,
}
我已经通过锁在 Mutex 上访问了这个内部映射:
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");
}
}
}
}
声明变量会改变这种行为的主要原因是什么?
最佳答案
The lock is released when the LockResult
goes out of scope .
现在我们必须深入scope rules regarding this temporary value .
临时值的范围是封闭语句。
在第一个片段中,这意味着锁在进入 if/let 结构之前超出了范围。没有死锁。
但是 if let
条件中临时值的范围是整个 if/let 结构:
the lifetime of temporary values is typically
- the innermost enclosing statement; the tail expression of a block is considered part of the statement that encloses the block, or
- the condition expression or the loop conditional expression if the temporary is created in the condition expression of an if or in the loop conditional expression of a while expression.
When a temporary value expression is being created that is assigned into a let declaration, however, the temporary is created with the lifetime of the enclosing block instead, as using the enclosing let declaration would be a guaranteed error (since a pointer to the temporary would be stored into a variable, but the temporary would be freed before the variable could be used)
在第二个片段中,锁的作用域覆盖了整个 if/let 结构。
这解释了为什么当您尝试在循环中再次锁定时,第一个锁仍然处于事件状态。
关于concurrency - 为什么 'if let' 会阻止使用 Mutex 的执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56681822/