从 Rust 中的全局 HashMap 获取项目的引用
Get item's reference from global HashMap in Rust
我正在尝试使用静态 HashMap 来存储一些我想在将来全局使用和修改的数据。我发现声明这样一个全局映射的某种方法是使用 lazy_static 和互斥锁来安全地共享数据。但是,当我想 return 这些对象作为参考时,我遇到了一些所有权问题,就像我在上面的代码中所做的那样:
use std::error::Error;
use std::collections::HashMap;
use std::sync::Mutex;
use super::domain::{Session, SessionRepository}; // object and trait declaration
lazy_static! {
static ref REPOSITORY: Mutex<HashMap<String, Session>> = {
let mut repo = HashMap::new();
Mutex::new(repo)
};
}
impl SessionRepository for REPOSITORY {
fn find(cookie: &str) -> Result<&mut Session, Box<dyn Error>> {
let mut repo = REPOSITORY.lock()?;
if let Some(sess) = repo.get_mut(cookie) {
return Ok(sess);
}
Err("Not found".into())
}
}
所以问题是:有什么方法可以正确地做到这一点吗? Rust 中是否存在我可以用来实现此行为的任何设计模式?
非常感谢!
你想要做的是正确地被编译器拒绝,因为如果你可以return一个引用,那么坏事就会发生。因为在函数 returns 之后,互斥锁不再被锁定,
- 其他一些线程可能会锁定互斥量并获得自己的会话可变引用,这违反了可变引用提供独占访问的规则。
- 其他一些线程可能会锁定互斥锁并从 HashMap 中删除 会话 — 现在您正在访问已释放的内存。
解决方案:每个会话都应该在其 自己的 Arc<Mutex<_>>
中。即:
lazy_static! {
static ref REPOSITORY: Mutex<HashMap<String, Arc<Mutex<Session>>>> = {
...
impl SessionRepository for REPOSITORY {
fn find(cookie: &str) -> Result<Arc<Mutex<Session>>, Box<dyn Error>> {
let mut repo = REPOSITORY.lock()?;
if let Some(sess) = repo.get(cookie) {
return Ok(Arc::clone(sess));
}
...
}
Arc
允许存储库和任何线程在其上调用 find()
并因此获得自己的 Arc
引用计数的克隆来保持会话处于活动状态指针。 Mutex
允许每个会话独立变异。
我正在尝试使用静态 HashMap
use std::error::Error;
use std::collections::HashMap;
use std::sync::Mutex;
use super::domain::{Session, SessionRepository}; // object and trait declaration
lazy_static! {
static ref REPOSITORY: Mutex<HashMap<String, Session>> = {
let mut repo = HashMap::new();
Mutex::new(repo)
};
}
impl SessionRepository for REPOSITORY {
fn find(cookie: &str) -> Result<&mut Session, Box<dyn Error>> {
let mut repo = REPOSITORY.lock()?;
if let Some(sess) = repo.get_mut(cookie) {
return Ok(sess);
}
Err("Not found".into())
}
}
所以问题是:有什么方法可以正确地做到这一点吗? Rust 中是否存在我可以用来实现此行为的任何设计模式?
非常感谢!
你想要做的是正确地被编译器拒绝,因为如果你可以return一个引用,那么坏事就会发生。因为在函数 returns 之后,互斥锁不再被锁定,
- 其他一些线程可能会锁定互斥量并获得自己的会话可变引用,这违反了可变引用提供独占访问的规则。
- 其他一些线程可能会锁定互斥锁并从 HashMap 中删除 会话 — 现在您正在访问已释放的内存。
解决方案:每个会话都应该在其 自己的 Arc<Mutex<_>>
中。即:
lazy_static! {
static ref REPOSITORY: Mutex<HashMap<String, Arc<Mutex<Session>>>> = {
...
impl SessionRepository for REPOSITORY {
fn find(cookie: &str) -> Result<Arc<Mutex<Session>>, Box<dyn Error>> {
let mut repo = REPOSITORY.lock()?;
if let Some(sess) = repo.get(cookie) {
return Ok(Arc::clone(sess));
}
...
}
Arc
允许存储库和任何线程在其上调用 find()
并因此获得自己的 Arc
引用计数的克隆来保持会话处于活动状态指针。 Mutex
允许每个会话独立变异。