Condividere con Arc e Mutex
Modifichi in sicurezza lo stato condiviso.
Condividere con Arc e Mutex è una lezione Learn Rust Coding gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Learn Rust Coding, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Learn Rust Coding include 4 lezioni in totale.
La necessità dello stato condiviso
A volte diversi thread devono leggere o aggiornare gli stessi dati. Trasferire la proprietà a un solo thread non è sufficiente.
Rust offre la proprietà condivisa sicura tra thread con Arc e la mutazione sicura con Mutex. Insieme consentono di gestire uno stato condiviso e mutabile.
Arc: conteggio atomico dei riferimenti
Arc significa conteggio atomico dei riferimenti. È simile a Rc, ma il suo contatore usa operazioni atomiche, quindi è sicuro tra thread.
Clonare un Arc non copia i dati. Incrementa solo il contatore e restituisce un altro handle allo stesso valore.
use std::sync::Arc;
fn main() {
let shared = Arc::new(vec![1, 2, 3]);
let clone = Arc::clone(&shared);
println!("{:?} {:?}", shared, clone);
}Condividere Arc tra thread
Per condividere dati di sola lettura, cloni Arc una volta per ogni thread e sposti ogni copia nel rispettivo thread. Tutti i thread puntano alla stessa allocazione.
Poiché Arc è Send e Sync, il codice viene compilato senza problemi.
use std::sync::Arc;
use std::thread;
fn main() {
let data = Arc::new(vec![10, 20, 30]);
let mut handles = vec![];
for i in 0..3 {
let d = Arc::clone(&data);
handles.push(thread::spawn(move || println!("{}", d[i])));
}
for h in handles { h.join().unwrap(); }
}Arc da solo è di sola lettura
Arc offre la proprietà condivisa, ma consente solo l'accesso condiviso e immutabile al valore interno.
Non è possibile modificare direttamente i dati tramite un Arc, perché più thread che lo possiedono contemporaneamente potrebbero generare una race condition. Serve la mutabilità interna con un lock.
Mutex: mutua esclusione
Un Mutex protegge i dati in modo che vi acceda un solo thread alla volta. Si chiama lock per ottenere l'accesso.
lock restituisce un Result; estraendone il valore si ottiene una guardia smart pointer. Gli altri thread rimangono bloccati finché la guardia non viene eliminata.
use std::sync::Mutex;
fn main() {
let m = Mutex::new(0);
{
let mut guard = m.lock().unwrap();
*guard += 5;
}
println!("{:?}", m);
}La guardia e RAII
Il valore restituito da lock è un MutexGuard. Si accede ai dati interni dereferenziandolo con *.
Quando la guardia esce dal suo ambito, il lock viene rilasciato automaticamente. Questo stile RAII evita di dimenticare di sbloccare il mutex.
Combinare Arc e Mutex
Per condividere uno stato mutabile tra thread, racchiuda un Mutex in un Arc. Arc condivide la proprietà; Mutex protegge la mutazione.
Questo schema, Arc<Mutex<T>>, è il modo standard di gestire uno stato condiviso e mutabile in Rust.
use std::sync::{Arc, Mutex};
fn main() {
let counter = Arc::new(Mutex::new(0));
let c = Arc::clone(&counter);
*c.lock().unwrap() += 1;
println!("{}", *counter.lock().unwrap());
}Un contatore condiviso
Qui dieci thread incrementano ciascuno un contatore condiviso. Ognuno clona Arc, blocca il Mutex e aggiunge uno.
Poiché il lock serializza l'accesso, il totale finale è sempre esattamente dieci.
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..10 {
let c = Arc::clone(&counter);
handles.push(thread::spawn(move || {
*c.lock().unwrap() += 1;
}));
}
for h in handles { h.join().unwrap(); }
println!("{}", *counter.lock().unwrap());
}Mantenga brevi le sezioni critiche
Il codice eseguito mentre un lock è acquisito costituisce la sezione critica. Gli altri thread rimangono in attesa, quindi è importante mantenerla breve.
Acquisisca il lock, esegua l'aggiornamento minimo e poi lo rilasci. Eviti calcoli onerosi o operazioni di I/O mentre detiene il lock.
use std::sync::Mutex;
fn main() {
let m = Mutex::new(Vec::new());
{
let mut v = m.lock().unwrap();
v.push(1);
} // lock released here
println!("{:?}", m.lock().unwrap());
}Deadlock e poisoning
Se un thread blocca due volte lo stesso Mutex, oppure due thread bloccano due mutex in ordine opposto, può verificarsi un deadlock e l'esecuzione può rimanere bloccata per sempre.
Se un thread va in panic mentre detiene un lock, il Mutex diventa poisoned e le successive chiamate a lock restituiscono un Err.
RwLock per molti lettori
Quando le letture sono molto più numerose delle scritture, RwLock può essere preferibile a Mutex. Consente molte letture concorrenti oppure un'unica scrittura esclusiva.
Utilizzi read per l'accesso condiviso e write per l'accesso esclusivo.
use std::sync::RwLock;
fn main() {
let lock = RwLock::new(5);
{
let r = lock.read().unwrap();
println!("read {}", *r);
}
*lock.write().unwrap() += 1;
println!("{}", *lock.read().unwrap());
}Verifica rapida
Verifichi la Sua comprensione di Arc e Mutex.
Riepilogo
Ha imparato che Arc condivide la proprietà tra i thread tramite il conteggio atomico dei riferimenti, ma consente solo l'accesso immutabile.
Un Mutex protegge le modifiche, fornendo una guardia che viene rilasciata al drop. Li combini come Arc<Mutex<T>> per ottenere uno stato mutabile condiviso, prestando attenzione a deadlock e poisoning.
Nel prossimo capitolo unirà i thread e raccoglierà i risultati.
Domande Frequenti
La lezione «Condividere con Arc e Mutex» è gratuita?
Sì — il testo completo di «Condividere con Arc e Mutex» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Learn Rust Coding, passa a CoddyKit PRO. Il corso Learn Rust Coding include 4 lezioni in totale.
Cosa imparerò in «Condividere con Arc e Mutex»?
Modifichi in sicurezza lo stato condiviso. Eserciti Learn Rust Coding con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Learn Rust Coding?
Non è richiesta alcuna esperienza precedente. Learn Rust Coding su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.
Quanto tempo richiede la lezione «Condividere con Arc e Mutex»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Learn Rust Coding?
Sì. Ogni lezione Learn Rust Coding include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Creare thread
- Spostare i dati nei thread
- Condividere con Arc e Mutex
- Unire i thread e raccogliere i risultati