patternrustMajor
When would you use a Mutex without an Arc?
Viewed 0 times
mutexyouarcusewouldwhenwithout
Problem
An extremely common pattern in Rust is
Arc>, where Arc provides the memory management, and Mutex provides safe multi-threaded access to the resource. What else could be used in place of Arc, and under what circumstances?Solution
Arc is of course the most common one in this context, but there are other pointer types that allow sharing. The major (and most common, in the rest of Rust) one is the shared reference &T. This normally doesn't work with std::thread::spawn'd threads, because it generally points to data controlled by some other thread, and is hence usually not 'static (particularly so when it is a &Mutex). However, one can use a scoped thread to create a thread that can share data with its parent. E.g.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]
}The type of
data in the closure passed to scope.spawn is in fact &Mutex (since it doesn't have the move keyword the closure is using the default capturing style: by reference).& and Arc are the two that can achieve this sort of thread-safe sharing in the standard library/language, but one can also write pointer types that offer thread-safe sharing in external libraries.However, moving away from the
Pointer> pattern, it can be useful to have the mutex and the sharing separated, e.g. Arc>> allows one to share some number of Mutex's without having to Arc each one individually, or maybe one wants to have some abstraction around a Mutex, and so wrap it in a struct:struct Wrapped {
data: Mutex,
}
impl Wrapped {
// fancy methods that abstract over `data.lock()`
}One would likely then see
Arc (or some other pointer that allows sharing).Code Snippets
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]
}struct Wrapped {
data: Mutex<T>,
}
impl Wrapped {
// fancy methods that abstract over `data.lock()`
}Context
Stack Overflow Q#33116317, score: 66
Revisions (0)
No revisions yet.