Rust 中一个极其常见的模式是 Arc<Mutex<T>>
, 其中Arc
提供内存管理,Mutex
提供对资源的安全多线程访问。还有什么可以用来代替Arc
, 在什么情况下?
最佳答案
Arc
在这种情况下当然是最常见的一种,但是还有其他允许共享的指针类型。主要的(也是最常见的,在 Rust 的其余部分)是共享引用 &T
.这通常不适用于 std::thread::spawn
'd 线程,因为它通常指向由其他线程控制的数据,因此通常不是 'static
(特别是当它是 &Mutex<T>
时)。但是,可以使用 scoped thread创建一个可以与其父级共享数据的线程。例如
use crossbeam; // 0.7.3
use std::sync::Mutex;
fn main() {
let data = Mutex::new(vec![0, 1]);
crossbeam::scope(|scope| {
// these run concurrently:
let _guard = scope.spawn(|_| {
data.lock().unwrap().push(2);
});
data.lock().unwrap().push(3);
})
.unwrap();
println!("{:?}", data.lock().unwrap());
// one of [0, 1, 2, 3] or [0, 1, 3, 2]
}
data
的类型在传递给 scope.spawn
的闭包中实际上是&Mutex<Vec<i32>>
(因为它没有 move
关键字,闭包使用默认的捕获样式:通过引用)。
&
和 Arc
有两种可以在标准库/语言中实现这种线程安全共享,但也可以编写在外部库中提供线程安全共享的指针类型。
但是,远离 Pointer<Mutex<...>>
模式,将互斥量和共享分开可能很有用,例如Arc<Vec<Mutex<T>>>
允许一个人分享一些 Mutex<T>
无需 Arc
每个人都是单独的,或者可能有人想围绕 Mutex
进行一些抽象,然后将其包装在 struct
中:
struct Wrapped {
data: Mutex<T>,
}
impl Wrapped {
// fancy methods that abstract over `data.lock()`
}
然后可能会看到 Arc<Wrapped>
(或其他一些允许共享的指针)。
关于rust - 什么时候使用没有 Arc 的 Mutex?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33116317/