【发布时间】:2015-10-14 03:51:18
【问题描述】:
Rust 中一个极其常见的模式是Arc<Mutex<T>>,其中Arc 提供内存管理,Mutex 提供对资源的安全多线程访问。还有什么可以用来代替Arc,在什么情况下?
【问题讨论】:
标签: rust
Rust 中一个极其常见的模式是Arc<Mutex<T>>,其中Arc 提供内存管理,Mutex 提供对资源的安全多线程访问。还有什么可以用来代替Arc,在什么情况下?
【问题讨论】:
标签: rust
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]
}
传递给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>(或其他一些允许共享的指针)。
【讨论】: