【发布时间】:2021-02-01 11:20:25
【问题描述】:
我必须锁定由 id 标识的不同进程。
所以我写了如下代码:
use std::collections::HashMap;
use std::ptr::null;
use std::sync::{Arc, Mutex, MutexGuard};
pub struct IDMutex {
m: Mutex<HashMap<String, Arc<Mutex<u8>>>>,
}
pub struct IDMutexGuard<'a> {
mutex: &'a IDMutex,
local_mutex: Arc<Mutex<u8>>,
local_guard: *const MutexGuard<'a, u8>,
id: String,
}
impl<'a> IDMutexGuard<'a> {
fn new(mutex: &'a IDMutex, id: String) -> Self {
let mut guard: MutexGuard<'_, _> = mutex.m.lock().unwrap();
let local_mutex = guard.entry(id.clone()).or_default().clone();
let mut res = Self {
mutex,
id,
local_mutex: local_mutex,
local_guard: null(),
};
res.local_guard = &res.local_mutex.lock().unwrap();
res
}
}
impl<'a> Drop for IDMutexGuard<'a> {
fn drop(&mut self) {
drop(&mut self.local_guard);
let mut guard = self.mutex.m.lock().unwrap();
guard.remove(&self.id);
}
}
impl IDMutex {
fn lock(&self, id: String) -> IDMutexGuard<'_> {
IDMutexGuard::new(&self, id)
}
}
它的实现类似于标准库的 Mutex 和 MutexGuard,但带有一个 id 参数,以便我可以锁定一些 id。但由于借用了规则,它并没有构建。
那么有什么解决这些问题的想法吗?
我知道正确的方法是挑选出共享状态,然后使用标准库的互斥锁来锁定它们。但由于某些历史原因,这确实是一种具有挑战性的方式,我希望我将来会这样做。
【问题讨论】:
-
从看它我完全不知道你的代码应该做什么,你能添加 soe cmets 吗?
-
您能否更详细地解释一下您的用例?您正在询问解决问题的具体方法。我觉得这种方法比它需要的更复杂,但如果不了解潜在问题就很难说。
-
锁定一个进程是什么意思?我以前没听过这句话,谷歌搜索也没有带来任何启发性的东西。通常我们谈论锁定资源,如文件和(对于线程)共享内存。直觉上我会假设锁定一个进程意味着暂停它,但我在你的代码中没有看到任何与多处理相关的东西,所以我想我一定是误解了。
-
我可以肯定地说
drop(&mut self.local_guard)没有做任何有用的事情。您需要std::ptr::drop_in_place将保护放在指针的另一端,并且您需要取消引用它。但这也是错误的,因为在new中,指针被初始化为当new返回时将被删除的局部变量的地址。所以这肯定不是你想要的。