Un modello estremamente comune in Rust è Arc<Mutex<T>>
, dove Arc
fornisce la gestione della memoria e Mutex
fornisce un accesso multi-thread sicuro alla risorsa. Che altro è possibile utilizzare al posto di Arc
e in quali circostanze?Quando useresti un Mutex senza arco?
risposta
Arc
è ovviamente il più comune in questo contesto, ma esistono altri tipi di puntatori che consentono la condivisione. Il principale (e il più comune, nel resto di Rust) è il riferimento condiviso &T
. Questo normalmente non funziona con i thread di std::thread::spawn
, perché generalmente punta a dati controllati da qualche altro thread, e quindi non è solitamente 'static
(in particolare quando è un &Mutex<T>
). Tuttavia, è possibile utilizzare uno scoped thread per creare un thread che può condividere dati con il suo genitore. Per esempio.
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]
}
Il tipo di data
nella chiusura passato a scope.spawn
è infatti &Mutex<Vec<i32>>
(dal momento che non ha la parola chiave move
la chiusura sta usando lo stile di cattura di default: per riferimento).
&
e Arc
sono i due che possono ottenere questo tipo di condivisione thread-safe nella libreria/lingua standard, ma si possono anche scrivere tipi di puntatori che offrono la condivisione thread-safe nelle librerie esterne.
Tuttavia, allontanandosi dal modello Pointer<Mutex<...>>
, può essere utile avere il mutex e la condivisione separati, ad es. Arc<Vec<Mutex<T>>>
permette di condividere un determinato numero di Mutex<T>
's, senza dover Arc
singolarmente, o forse si vuole avere una certa astrazione intorno ad un Mutex
, e quindi avvolgerla in un struct
:
struct Wrapped {
data: Mutex<T>
}
impl Wrapped {
// fancy methods that abstract over `data.lock()`
}
Uno sarebbe probabilmente poi vedi Arc<Wrapped>
(o qualche altro puntatore che consente la condivisione).
il collegamento è morto fyi, come per la loro pagina cassa: "Questa cassa è obsoleta.Il progetto Crossbeam è attualmente in un periodo di transizione.Siamo riscrivendo il depuratore di epoca, così come molte altre utilità e l'aggiunta di nuove strutture. Per seguire i progressi, si prega di dare un'occhiata alle altre casse nel progetto qui.Quando la transizione è completa, questa cassa verrà aggiornata per utilizzare il nuovo codice. " – EmmaGamma