Rust(新手):内存数据库的多个线程对同一底层数组的读写(可变)访问



我正在考虑将Rust作为我的主要开发语言,而不是Go,所以我一直在阅读文档。

我的工作需要做的一件事是从多个线程读取和写入一个自定义数据库,该数据库以单个大数组的形式存储在内存中,大小可能为32GB。数据库函数是为了避免竞争条件而设计的,并且在必要时使用互斥或原子基元。

Rust-doc暗示数组只能在单个线程上是可变的(可写的(,也不能在多个线程上是不可变的(只读的(,并且不能在一个线程上可写,在另一个线程同时可读。那么如何使用内存中的数据库。。。?这没有道理!

我错了吗?

请原谅,我不能给出任何具体的Rust示例,因为我仍在学习Rust语法,老实说,在花时间学习一门我将无法使用的语言之前,我需要知道这个问题的答案。

有一种不安全的方法,即使用UnsafeCell,它返回指向其内部数据的可变原始指针。借用检查器不会跟踪这些,因此您必须确保不变量得到的支持

pub struct UnsafeVec<T> {
data: UnsafeCell<Vec<T>>
}
impl<T> UnsafeVec<T> {
pub fn new() -> Self {
UnsafeVec { data: UnsafeCell::new(Vec::new()) }
}
pub fn push(&mut self, arg: T) {
self.data.get_mut().push(arg)
}
pub unsafe fn index_mut(&self, index: usize) -> &mut T {
&mut (*self.data.get())[index]
}
}
unsafe impl<T> Sync for UnsafeVec<T> {}
unsafe impl<T> Send for UnsafeVec<T> {}

它允许您编写

fn main() {
let mut unsafe_vec = UnsafeVec::<i32>::new();
unsafe_vec.push(15);
unsafe {
*unsafe_vec.index_mut(0) += 1;
}
}

index_mut方法允许使用不可变的引用来修改内部向量。Sync和Send特性向编译器发出信号,表明该类型可以在线程之间安全共享,只有手动防止可能的数据竞争时,这才是真的!。同样,这是一个不安全的选项,需要您自己维护不变量。

最新更新