rust mutex 借来的值活得不够长
rust mutex borrowed value does not live long enough
enter image description here
我想在执行器操作之前锁定多个页面,怎么办?
首先,从代码来看,似乎可以多次点击同一个条目。这意味着您将立即死锁,因为第二次访问将尝试锁定已经锁定的互斥锁。您可能应该使用 or_insert_with
以便仅在没有该密钥的条目时才获取锁。
其次,好吧MutexGuard
(无论是tokio还是stdlib)借用了互斥量。由于 Mutex 仅在迭代期间借用,因此 MutexGuard 不能比它长。解决这个问题的方法是延长 Mutex 的生命周期,例如通过将它添加到迭代之外的集合,然后借用 that。此时你可能需要 两次 次迭代,因为如果你将一个锁推入“所有者”集合然后立即借用它,该集合将在下一次迭代中被借用而你不会能够插入新项目:
let mut locks = vec![];
let mut page_map = HashMap::new();
for key in keys {
let page = store.get(key).unwrap();
locks.push((key, page.clone()));
}
for (key, lock) in &locks {
page_map.entry(key).or_insert_with(|| lock.lock());
}
虽然你遇到了第三个问题(和第二个可能的死锁):如果这可以同时执行两次,那么两个调用可能 key_feature_map
的顺序不同,这意味着一个调用可能会锁定页面 A 然后尝试获取页面 B,而第二个调用将锁定页面 B,现在尝试获取页面 A。
两个调用都在等待对方的锁,所以它们会死锁。
enter image description here
我想在执行器操作之前锁定多个页面,怎么办?
首先,从代码来看,似乎可以多次点击同一个条目。这意味着您将立即死锁,因为第二次访问将尝试锁定已经锁定的互斥锁。您可能应该使用 or_insert_with
以便仅在没有该密钥的条目时才获取锁。
其次,好吧MutexGuard
(无论是tokio还是stdlib)借用了互斥量。由于 Mutex 仅在迭代期间借用,因此 MutexGuard 不能比它长。解决这个问题的方法是延长 Mutex 的生命周期,例如通过将它添加到迭代之外的集合,然后借用 that。此时你可能需要 两次 次迭代,因为如果你将一个锁推入“所有者”集合然后立即借用它,该集合将在下一次迭代中被借用而你不会能够插入新项目:
let mut locks = vec![];
let mut page_map = HashMap::new();
for key in keys {
let page = store.get(key).unwrap();
locks.push((key, page.clone()));
}
for (key, lock) in &locks {
page_map.entry(key).or_insert_with(|| lock.lock());
}
虽然你遇到了第三个问题(和第二个可能的死锁):如果这可以同时执行两次,那么两个调用可能 key_feature_map
的顺序不同,这意味着一个调用可能会锁定页面 A 然后尝试获取页面 B,而第二个调用将锁定页面 B,现在尝试获取页面 A。
两个调用都在等待对方的锁,所以它们会死锁。