如何解决Arc 结构和多个读取器和单个写入器,没有重叠的内存访问
结构体 Outer
包装了 Inner
。我知道 Inner
可以有多个读者,因此我将 Inner
包装在 Arc
中。读者只能通过调用 Inner
来访问 Outer::new_reader
。
struct Inner(Box<[u8]>);
struct Outer {
inner: Arc<Inner>
}
impl Outer {
fn new_reader(&self) -> OuterReader {
...
}
}
struct OuterReader {
Arc<Inner>
}
我也知道可以有一个单一作者(在运行时强制执行)。读者和作者的访问模式是这样的,我们知道没有数据竞争; OuterReader
的实例只能访问 Inner
中 OuterWriter
初始化的内存区域,并且永远不会再次访问)。 OuterWriter
可以替换 Inner
,但:1) 此替换不应影响当前的读者,2) 应该对未来的读者可见。
我们最好不要锁定所有数据,因为:1) OuterWriter
执行的其他访问模式更为频繁且对性能至关重要。 2) OuterWriter
不应被阻塞一段不确定的时间(例如被长时间读取阻塞)。 3) 我们没有利用 OuterReaders
和 OuterWriter
在内存访问中不重叠的优势。
struct OuterWriter {
inner: Arc<Inner>
}
impl OuterWriter {
fn replace_inner(&mut self) {
self.inner = Arc::new(Inner::new());
}
}
在上面的代码中,调用 Outer::new_reader
的新读者不会看到新的 Inner
!为了解决这个问题,我使用了双 Arc
的笨拙设置 - 当没有其他引用指向 Arc
时,利用 Arc<Inner>
来删除/释放。
struct Outer {
inner: Arc<Arc<Inner>>,lock: Arc<Mutex>,}
impl Outer {
fn new_reader(&self) -> OuterReader {
// Lock access to changing the Arc<Inner>. The time
// lock is held is constant - only the time taken to clone an Arc
self.lock.lock();
OuterReader::new((*self.inner).clone())
}
}·
struct OuterWriter {
inner: Arc<Arc<Inner>>,}
impl OuterWriter {
fn replace_inner(&mut self) {
self.lock.lock(); // Lock to prevent new readers while replacing inner
// Safe because we guarantee at runtime that there is only one writer.
// Readers can only access from Outer::new_reader() w/c is locked out
// due to mutex
unsafe {
*Arc::get_mut_unchecked(self.inner) = Arc::new(Inner::new());
}
}
fn other_operation() {
// Acts on areas that will definitely not be read so does not need to
// hide behind a lock
}
}
有没有/一定有更好的方法。
我肯定缺少一个容器或指针类型(AtomicPointer
?)或同步原语,它们可以使这不那么麻烦。
有什么想法吗?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。