Ce face Mutex::lock
lock() așteaptă până când niciun alt fir nu ține mutex-ul, apoi returnează un MutexGuard. Guard-ul se folosește ca o referință mutabilă (*guard += 1, guard.push(x)) și eliberează mutex-ul când dispare. Eliberarea mai devreme se face cu drop(guard).
try_lock() nu așteaptă: returnează Err(WouldBlock) dacă mutex-ul este ocupat. Un Err(Poisoned) de la oricare dintre ele înseamnă că un fir a intrat în panică ținând mutex-ul; datele sunt totuși accesibile cu into_inner() pe eroare.
Ce returnează
LockResult<MutexGuard<T>>, adică Result cu guard-ul sau cu eroarea de otrăvire.
Exemple
Exemplul 1: Guard-ul și eliberarea lui
use std::sync::Mutex;
fn main() {
let sold = Mutex::new(100);
let mut g = sold.lock().unwrap();
*g -= 30;
println!("în timp ce țin lock-ul, try_lock reușește: {}", sold.try_lock().is_ok());
drop(g);
println!("după drop, try_lock reușește: {}", sold.try_lock().is_ok());
println!("sold: {} lei", sold.lock().unwrap());
}
Rezultat
în timp ce țin lock-ul, try_lock reușește: false
după drop, try_lock reușește: true
sold: 70 lei
Exemplul 2: Mutex otrăvit după o panică
Firul intră în panică în timp ce ține lock-ul. Hook-ul de panică este oprit, ca să nu apară mesajul cu numărul firului.
use std::panic;
use std::sync::Mutex;
use std::thread;
fn main() {
panic::set_hook(Box::new(|_| {}));
let date = Mutex::new(vec![1, 2, 3]);
thread::scope(|s| {
let r = s
.spawn(|| {
let mut g = date.lock().unwrap();
g.push(4);
panic!("eroare în timpul modificării");
})
.join();
println!("firul a intrat în panică: {}", r.is_err());
});
match date.lock() {
Ok(g) => println!("date: {:?}", *g),
Err(otravit) => println!("mutex otrăvit, datele rămase: {:?}", *otravit.into_inner()),
}
}
Rezultat
firul a intrat în panică: true
mutex otrăvit, datele rămase: [1, 2, 3, 4]
Greșeli frecvente
- Scrii
let x = m.lock().unwrap().clone();și apoi te miri că modificările pexnu ajung în mutex: ai lucrat pe o copie. - Faci
match m.lock().unwrap().get(0) { ... }și în ramuri faci din noulock(): guard-ul temporar trăiește până la sfârșitul luimatch, deci firul se blochează.
Comenzi înrudite
Mutex: Protejează o valoare folosită din mai multe fire: lock() așteaptă până când firul curent este singurul cu acces.RwLock: Lacăt cititori-scriitor: mai multe fire pot citi în același timp, dar scrierea are nevoie de acces exclusiv.mem::drop: Distruge o valoare imediat, înainte de sfârșitul blocului: eliberează memoria, închide fișierul, deblochează mutex-ul.