Ce face RwLock
RwLock<T> seamănă cu Mutex, dar face diferența între citire și scriere. read() dă un guard de citire; pot exista mulți în paralel. write() dă un guard de scriere, care așteaptă până nu mai există niciun cititor sau scriitor.
Este util pentru date citite des și modificate rar: o configurare, un cache, un tabel de prețuri. Dacă scrierile sunt frecvente, un Mutex simplu este de obicei la fel de bun. Ca la Mutex, rezultatul este Result din cauza otrăvirii, deci se scrie .unwrap().
Parametri
| Parametru | Descriere |
|---|---|
t |
Valoarea protejată (la new). |
Ce returnează
read: guard de citire (ca &T). write: guard de scriere (ca &mut T).
Exemple
Exemplul 1: Configurare citită de mai multe fire
Cele trei fire citesc în paralel. Rezultatele vin prin join, în ordine. Scrierea se face după.
use std::sync::RwLock;
use std::thread;
fn main() {
let curs_euro = RwLock::new(4.97);
thread::scope(|s| {
let fire: Vec<_> = [100.0, 250.0, 40.0]
.into_iter()
.map(|lei| {
let curs = &curs_euro;
s.spawn(move || {
let c = curs.read().unwrap();
format!("{lei} lei = {:.2} euro", lei / *c)
})
})
.collect();
for f in fire {
println!("{}", f.join().unwrap());
}
});
*curs_euro.write().unwrap() = 5.02;
println!("curs nou: {}", curs_euro.read().unwrap());
}
Rezultat
100 lei = 20.12 euro
250 lei = 50.30 euro
40 lei = 8.05 euro
curs nou: 5.02
Exemplul 2: Doi cititori în același timp
Al doilea read reușește chiar dacă primul guard există încă; try_write eșuează cât timp există cititori.
use std::sync::RwLock;
fn main() {
let orase = RwLock::new(vec!["Iași", "Cluj"]);
let r1 = orase.read().unwrap();
let r2 = orase.read().unwrap();
println!("r1 = {:?}, r2 = {:?}", *r1, *r2);
println!("pot scrie acum: {}", orase.try_write().is_ok());
drop(r1);
drop(r2);
orase.write().unwrap().push("Sibiu");
println!("după scriere: {:?}", orase.read().unwrap());
}
Rezultat
r1 = ["Iași", "Cluj"], r2 = ["Iași", "Cluj"]
pot scrie acum: false
după scriere: ["Iași", "Cluj", "Sibiu"]
Greșeli frecvente
- Ceri
write()în același fir în care ții încă un guard deread(): firul se blochează pentru totdeauna. - Folosești
RwLockpentru date modificate des: costul de gestionare este mai mare decât laMutexși nu câștigi nimic.
Comenzi înrudite
Mutex: Protejează o valoare folosită din mai multe fire: lock() așteaptă până când firul curent este singurul cu acces.Arc: Varianta lui Rc care poate fi împărțită între fire: contorul de proprietari este actualizat atomic.OnceLock: Celulă care primește o valoare o singură dată, sigur între fire; ideală pentru valori globale calculate la prima folosire.