2015-10-14 13 views
11

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

17

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).

+2

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