Rust中非常常见的模式是Arc<Mutex<T>>
,其中Arc
提供内存管理,Mutex
提供对资源的安全多线程访问。还有什么可以代替Arc
,以及在什么情况下?
答案 0 :(得分:23)
Arc
当然是此上下文中最常见的一种,但还有其他指针类型允许共享。主要(在Rust的其余部分中最常见)一个是共享引用&T
。这通常不适用于std::thread::spawn
个线程,因为它通常指向由其他线程控制的数据,因此通常不是'static
(尤其是当它是&Mutex<T>
时extern crate crossbeam;
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);
});
println!("{:?}", *data.lock().unwrap());
// one of [0, 1, 2, 3] or [0, 1, 3, 2]
}
)。但是,可以使用scoped thread创建可与其父级共享数据的线程。 E.g。
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>
然后可能会看到Radgrid1.Rebind
(或其他允许共享的指针)。