如何获得一个Arc<RwLock<Foo>>的只读版本?

4

我有一个 Arc<RwLock<Foo>>

是否有一种方法可以在其中不使用 RwLock 的 write() 方法?即是否有某种形式的 RLock 可以从 RwLock 中创建。

应用场景:我有一个 Foo。我的代码中有多个部分需要对 Foo 进行修改(因此需要 RwLock),但大部分代码只能以只读方式访问 Foo。

是否有实现这一点的方法?或者是否有一种方法可以在没有使用 RwLock 的情况下完成这个目标?


1
如何在不复制数据的情况下将只读数据发送到其他线程? - Ömer Erden
2
只需从read返回LockGuard(甚至是包装的Result)。 - Netwave
1
很难没有具体的例子就回答,但您可以尝试不使用RwLock,而是使用Arc::get_mut() - Chayim Friedman
很遗憾,我有多个Arc<RwLock<Foo>>的克隆体在不同的线程中。 - fadedbee
@Netwave 如果“只读”引用需要在进程的生命周期内保持活动状态,这个方法是否可行?或者它会阻塞写入操作? - fadedbee
1
@fadedbee,你需要在某个时候释放锁定,你不应该引用这个独占区域(因为它将在整个时间内被锁定,所以你无法写入),但你可以随意拥有尽可能多的读取访问。 - Netwave
1个回答

3

编写你自己的结构体,包含 Arc<RwLock<Foo>>

#[derive(Clone, Debug)]
pub struct FooReadOnly(Arc<RwLock<Foo>>);

impl FooReadOnly {
    pub fn read(&self) -> LockResult<RwLockReadGuard<'_, Foo>> {
        self.0.read()
    }

}

(一个充分完整的版本还将包含对try_read()的包装器。)
值得注意的通用模式是:你的数据类型不再被“可见地”放在Arc >中,而是你的公共类型“包含”了Arc。这比暴露Arc要灵活得多,可以提供更多种类的“句柄”。这是Rust中相当常见的模式-如果你曾经使用过库类型,并注意到你可以克隆它并获得对同一内容的另一个句柄,那么很有可能它内部正在做同样的事情(如果它不是实际上是一个操作系统资源的句柄,例如文件描述符)。
如果你想完全隐藏实现细节,你还可以封装RwLockReadGuard-它只需要实现Deref并将其转发给guard。这样的包装器也可以做一些类似于Deref到Foo的某个“部分”而不是一个&Foo的事情。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接