Rust中一个非常常见的模式是Arc<Mutex<T>>
,其中Arc
提供内存管理,Mutex
提供安全的多线程访问资源。还有什么其他东西可以代替Arc
,在什么情况下使用?
Rust中一个非常常见的模式是Arc<Mutex<T>>
,其中Arc
提供内存管理,Mutex
提供安全的多线程访问资源。还有什么其他东西可以代替Arc
,在什么情况下使用?
Arc
是在这个上下文中最常见的一种,但还有其他指针类型可以实现共享。主要的(也是Rust中其余部分中最常见的)是共享引用&T
。这通常不适用于使用std::thread::spawn
创建的线程,因为它通常指向由其他线程控制的数据,并且通常不是'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]
}
scope.spawn
传递的闭包中的data
类型事实上是&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>
(或其他允许共享的指针)。