试图从RwLock返回引用,"借来的值不够长"错误

jer*_*roe 3 hashmap rust rwlock borrow-checker

我最近一直在研究我的第一个Rust项目,但遇到了障碍.我正在使用HashMap映射StringAtomicUsize整数.该HashMap被保护的RwLock,允许并发访问.我希望能够返回对AtomicUsize值的引用HashMap,但是如果我尝试将这些引用返回给调用者,那么RwLockWriteGuard我的生命周期就会出现错误borrowed value does not live long enough.我抄录如下一个小例子,把上锈操场同样的例子在这里.

use std::collections::HashMap;
use std::sync::RwLock;
use std::sync::atomic::{AtomicUsize, Ordering};

struct Bar {
    val: AtomicUsize
}

impl Bar {
    pub fn new() -> Self {
        Bar { val: AtomicUsize::new(0) }
    }
}

struct Foo {
    map: RwLock<HashMap<String, Bar>>
}


impl Foo {
    pub fn get(&self, key: String) -> &Bar {
        self.map.write().unwrap().entry(key).or_insert(Bar::new())
    }
}

fn main() {
    let foo = Foo {map: RwLock::new(HashMap::new())};
    let bar = foo.get("key".to_string());
}
Run Code Online (Sandbox Code Playgroud)

我得到的错误发生在线上:

self.map.write().unwrap().entry(key).or_insert(Bar::new())
Run Code Online (Sandbox Code Playgroud)

而且是因为借来的价值不够长.我读过一些其他职位讨论这个错误,这一个特别是尤为重要.阅读之后,我可以认为从互斥锁返回的值的生命周期必须小于互斥锁的生命周期,这似乎完全排除了我正在尝试做的事情.我可以看到为什么这是不可能的,因为如果我们有一个指向Hashmap的指针而另一个将值插入到互斥锁中导致它被调整大小,那么我们将有一个悬空指针.

那么,我的问题是双重的.首先,我只是好奇我是否正确理解了这个问题,或者是否还有其他原因导致我不能做我试图做的事情?而我的第二个问题是,是否有另一种方法可以实现我想要做的事情而没有Box原子整数并将其存储在HashMap?这样的方法似乎应该对我有用,因为我们可以返回一个指向Boxed始终有效的值的指针.然而,似乎这种方法效率低下,因为它需要一个额外的指针间接层和一个额外的分配.谢谢!

Chr*_*son 6

你是正确的,你不能返回一个比它更长的东西的引用MutexGuard,因为这会导致一个可能悬空的指针.

但是,将内容包装在一起Box将无济于事!A Box是一个拥有的指针,除了参考生命周期之外,重定向的行为类似于包含的值.毕竟,如果您返回对它的引用,其他人可能会将其从中删除HashMap并取消分配.

根据您对参考的要求,我可以考虑几个选项:

  1. 而不是Box将值包装起来Arc.您可以克隆Arc从中获取的内容HashMap,并且多个引用可以同时存在.

  2. 你也可以MutexGuard随参考一起返回; 看到这个问题,如果您只想对值进行操作然后相对较快地删除引用,这将很有效.这将保持互斥锁持续直到您完成它.