【问题标题】:Using RwLock.read() on a mutable struct在可变结构上使用 RwLock.read()
【发布时间】:2021-12-05 14:23:03
【问题描述】:

我正在尝试在可变结构周围使用 RwLock,但我无法编译它,我不知道为什么。

这是一个最低限度的代码示例:

use std::sync::RwLock;
use lru::LruCache;

fn main() {
        let mut cache: LruCache<String,String> = LruCache::new(100);
        cache.put("test".to_string(), "test_value".to_string());
        let lock_cache = RwLock::new(cache);
        let rc = lock_cache.read();
        let res = rc.unwrap().get("test");
        assert_eq!(res.unwrap().as_str(), "test_value");
}

LruCache 来自外部 Rust 板条箱(但我认为它在问题中没有特定作用)。 编译器抱怨此消息:

error[E0596]: cannot borrow data in a dereference of `RwLockReadGuard<'_, LruCache<String, String>>` as mutable
   --> tests/cache_test.rs:295:15
    |
295 |     let res = rc.unwrap().get("test");
    |               ^^^^^^^^^^^ cannot borrow as mutable
    |
    = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `RwLockReadGuard<'_, LruCache<String, String>>`

我检查了RwLock 的文档,而RwLockWriteGuard 确实实现了DerefMutRwLockReadGuard 没有。

我对 Rust 很陌生,所以我很确定我做错了什么。有没有办法解决 DerefMut 是必需但未实现的编译器错误?

编辑我更改了代码,以便可以从主文件轻松执行。

【问题讨论】:

  • LruCache 来自哪里?
  • 嗨 Andrea,欢迎来到Stack Overflow,您能否修改您的代码以便对其进行测试。看看How to Ask ;)
  • @justinas 它来自一个名为lru的板条箱
  • .read() 方法用于RwLockread 部分,它提供对受保护值的读取,也就是不可变的访问。也许你想要.write()

标签: rust borrow-checker rwlock


【解决方案1】:

LruCache::get 需要&amp;mut self,根据其签名 (docs):

pub fn get<'a, Q>(&'a mut self, k: &Q) -> Option<&'a V> 

这是因为 LRU 缓存的特性:为了跟踪最近使用的项目,缓存需要修改(写入)其状态:

<...> 如果存在,则将键移动到 LRU 列表的头部。

即使您正在执行“读取”操作。

因此,在您的情况下,RwLock 不会比Mutex 赢得您任何好处,因为无论如何您都必须获得写锁。最简单的选择是改用Mutex&lt;LruCache&lt;K, V&gt;&gt;,或者选择另一种缓存方式。

【讨论】:

  • 谢谢,我应该考虑一下 LRU 是如何工作的,你说得对!我已经有了一个使用 Mutex&lt;LruCache&lt;K,V&gt;&gt; 的项目的工作版本,并且正在尝试使用 RwLock,所以我会坚持下去。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-08
  • 1970-01-01
  • 2016-09-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多