Rust 如何在互斥锁内的静态哈希映射中返回对项的引用?
我试图访问静态hashmap进行读写,但总是出现错误:Rust 如何在互斥锁内的静态哈希映射中返回对项的引用?,rust,lazy-static,Rust,Lazy Static,我试图访问静态hashmap进行读写,但总是出现错误: use std::collections::HashMap; use std::sync::Mutex; pub struct ModuleItem { pub absolute_path: String, } lazy_static! { static ref MODULE_MAP: Mutex<HashMap<i32, ModuleItem>> = Mutex::new(HashMap::ne
use std::collections::HashMap;
use std::sync::Mutex;
pub struct ModuleItem {
pub absolute_path: String,
}
lazy_static! {
static ref MODULE_MAP: Mutex<HashMap<i32, ModuleItem>> = Mutex::new(HashMap::new());
}
pub fn insert(identity_hash: i32, module_item: ModuleItem) {
MODULE_MAP
.lock()
.unwrap()
.insert(identity_hash, module_item);
}
pub fn get(identity_hash: i32) -> Option<&'static ModuleItem> {
MODULE_MAP.lock().unwrap().get(&identity_hash).clone()
}
使用std::collections::HashMap;
使用std::sync::Mutex;
pub结构ModuleItem{
pub绝对路径:String,
}
懒惰的人!{
静态ref模块映射:Mutex=Mutex::new(HashMap::new());
}
发布fn插入(标识\u散列:i32,模块\u项:模块项){
模块映射
.lock()
.unwrap()
.插入(标识\u散列、模块\u项);
}
pub fn get(identity\u hash:i32)->选项
我试过使用.clone()、.clone()甚至什么都没试过,但都没能成功。你能帮我吗
克隆所做的一切就是克隆底层结构,在本例中,它是一个&ModuleItem
,因此它只克隆引用,而您仍然有一个引用,您无法返回该引用,因为您只有在持有锁时才能访问hashmap的内容(否则它无法工作)
Option::cloned
实际上克隆了引用所持有的对象,但由于无法克隆ModuleItem,因此不会在此处编译
首先,您必须返回一个选项
,您不能返回对映射内容的引用,因为锁将在函数结束时释放,并且您不能跨互斥体边界保留hashmap内容的句柄,因为它们可能随时消失(例如,其他线程可能会移动它们,甚至完全清除映射)
然后通过在ModuleItem
上派生Clone
(然后调用Option::cloned
)或“手动”创建新的ModuleItem来复制ModuleItem,例如
pub-fn-get(identity\u hash:i32)->选项{
模块| MAP.lock().unwrap().get(&identity_hash).MAP(| m|
ModuleItem{absolute_path:m.absolute_path.clone()}
)
}
如果您经常需要获取
密钥并担心性能,您可以随时存储Arc
。这有一定的成本(因为它是一个指针,所以您的字符串现在位于两个指针后面),但是克隆弧非常便宜
为了避免双指针,您可以将ModuleItem
设置为非大小类型,并让它存储str
,但是。。。这很难使用,因此我不推荐使用。函数get
不能使用静态生存期,因为数据不会在程序的整个生存期内生存():
“作为引用生存期”static表示引用指向的数据在运行程序的整个生存期内都有效。它仍然可以被强制缩短寿命
因此,您必须返回非静态引用或HashMap
值的副本。引用不可能,因为返回一个MutexGuard
,它是一个本地变量,因此是一个临时变量,保存HashMap
。和HashMap
的get()
返回一个引用
由于临时MutexGuard
将在函数结束时销毁,因此get
返回的引用将指向临时值
要解决此问题,可以使ModuleItem
clonable并返回值的副本:
使用std::collections::HashMap;
使用std::sync::Mutex;
#[衍生(克隆)]
pub结构ModuleItem{
pub绝对路径:String,
}
懒惰的静态::懒惰的静态!{
静态ref模块映射:Mutex=Mutex::new(HashMap::new());
}
发布fn插入(标识\u散列:i32,模块\u项:模块项){
模块映射
.lock()
.unwrap()
.插入(标识\u散列、模块\u项);
}
pub fn get(identity\u hash:i32)->选项{
模块_MAP.lock().unwrap().get(&identity_hash).cloned()
}
Thx查看两个答案。两者似乎都有效。它们之间的区别是什么?在另一个答案中,您必须通过map
功能手动复制数据。在我的回答中,复制是通过从Clone
派生并使用Clone
方法完成的