首页 > 解决方案 > 如何从包装在 Arc 中的 Hashmap 和 Rust 中的 Mutex 返回对值的引用?

问题描述

我在返回HashMap<String,String>由 Arc 和 Mutex 包装以在线程之间共享的值的引用时遇到了一些麻烦。代码是这样的:


use std::sync::{Arc,Mutex};
use std::collections::HashMap;

struct Hey{
    a:Arc<Mutex<HashMap<String, String>>>
}


impl Hey {
    fn get(&self,key:&String)->&String{
        self.a.lock().unwrap().get(key).unwrap()
    }
}

如上图,代码因为returns a value referencing data owned by the current function. 我知道lock()返回 MutexGuard 这是一个局部变量。但是我怎样才能实现这种方法来获取对 HashMap 中值的引用。如果我不能,Rust 禁止这样做的动机是什么?

标签: rust

解决方案


让我解释一下为什么 rustc 认为你的代码是错误的。

  1. 只有当您锁定了受 Mutex 保护的值时,您才能与它进行交互。
  2. 由 RAII 警卫处理的锁。

所以,我对你的代码脱糖:

fn get(&self,key:&String)->&String{
   let lock = self.a.lock().unwrap();
   let reference = lock.get(key).unwrap();
   drop(lock); // release your lock
   // We return reference to data which doesn't protected by Mutex!
   // Someone can delete item from hashmap and you would read deleted data
   // Use-After-Free is UB so rustc forbid that
   return reference;
}

可能您需要Arcs用作值:

#[derive(Default)]
struct Hey{
    a:Arc<RwLock<HashMap<String, Arc<String>>>>
}
fn get(&self,key:&String)->Arc<String>{
    self.a.lock().unwrap().get(key).unwrap().clone()
}

PS 此外,您可以使用Arc<str>(我会推荐),这将使您免于额外的指针间接。它可以从 String:let arc: Arc<str> = my_string.into();Arc::from(my_string)


推荐阅读