2015-06-12 11 views
8

Spesso, quando delegato il lavoro ai thread, ho un dato che sopravvivrà a tutti i thread. Un esempio potrebbe essere numbers nel seguente esempio:È possibile condividere dati con thread senza clonazione?

use std::thread; 

fn main() { 
    let numbers = vec![1, 2, 3]; 

    let thread_a = thread::spawn(|| { println!("{}", numbers.len()); }); 
    let thread_b = thread::spawn(|| { println!("{}", numbers.len()); }); 

    thread_a.join().unwrap(); 
    thread_b.join().unwrap(); 
} 

Non è modificato da nessuna parte, ed a causa delle join s, è garantito che i fili sono fatte di usarlo. Tuttavia, il controllore del prestito di Rust non è in grado di dirlo.

Le soluzioni che ho visto finora riguardano la clonazione di un dato (o la clonazione di un Arc dei dati). È possibile farlo senza clonazione?

risposta

5

No. Ma si potrebbe avere l'idea sbagliata: la clonazione di un Arc sta semplicemente incrementando un contatore di riferimento e facendo una copia di un puntatore; non esegue alcuna allocazione. (Edit: Certo, mettere qualcosa in un Arc comporta uno stanziamento, ma poi, si sta già assegnando al fine di costruire la vec!, quindi un ulteriore stanziamento di dimensione fissa non è probabile che male.)

(per inciso, se tutto quello che davvero necessità è la lunghezza, si può solo calcolare che di fuori la chiusura del thread e conservarla in una variabile, un usize non ha problemi che attraversano un confine thread.)

la questione è che, al momento, i prestiti sono lessicali, quindi anche se è stato possibile per il compilatore dedurre dall'uso di join() che un dato thread è legato a una durata limitata ... non ci prova nemmeno.

Ci era un thread::scoped costruttore che vi ha permesso di passare in non 'static riferimenti, ma che doveva essere de-stabilizzato a causa di un problema di sicurezza di memoria. C'è una sostituzione in arrivo, ma (a partire da Rust 1.0 e probabilmente 1.1) non è ancora pronto.

Quindi per ora, nel codice di sicurezza o non-notturno ... no, non è possibile.

+1

Bene, per mettere qualcosa in 'Arc' tu * fai * eseguire un'assegnazione. –

+0

@MatthieuM. Buon punto; aggiunto una nota. –