3

我最近一直在做我的第一个 Rust 项目,但遇到了障碍。我正在使用s 到整数的HashMap映射。受a 保护以允许并发访问。我希望能够返回对. 我在下面复制了一个最小的示例,并将相同的示例放在 Rust 操场StringAtomicUsizeHashMapRwLockAtomicUsizeHashMapRwLockWriteGuardborrowed 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());
}

我得到的错误发生在线:

self.map.write().unwrap().entry(key).or_insert(Bar::new())

并且是因为借来的价值的寿命不够长。我已经阅读了其他一些讨论此错误的帖子,尤其是这一篇特别相关。读完之后,我可以收集到从互斥锁返回的值的生命周期必须小于互斥锁的生命周期,这似乎完全排除了我正在尝试做的事情。我明白为什么这是不可能的,因为如果我们有一个指向 Hashmap 的指针,而另一个将值插入到互斥体中导致它被调整大小,那么我们将有一个悬空指针。

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

4

1 回答 1

8

您是正确的,您不能返回对超过 的东西的引用MutexGuard,因为这会导致可能的悬空指针。

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

根据您要对参考执行的操作,我可以想到几个选项:

  1. 而不是Boxing 值,将它们包装在Arc. Arc从 中获取时,您将克隆HashMap,并且多个引用可以同时存在。

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

于 2016-10-28T07:43:31.670 回答