Mutex<T>
- Rust kursu
- İleri seviye
- Ders 14/81
- 4 dk
Mutex<T> ile karşılıklı dışlama (mutual exclusion) yaparsın.
Mutex<T>
Mutex<T> (karşılıklı dışlama), veriye aynı anda yalnızca bir thread'in erişmesini sağlar. lock() bir guard döndürür; guard yaşadığı sürece kilit tutulur ve guard bırakılınca kilit kendiliğinden açılır:
use std::sync::{Arc, Mutex};
let sayac = Arc::new(Mutex::new(0));
let mut h = Vec::new();
for _ in 0..8 {
let s = Arc::clone(&sayac);
h.push(thread::spawn(move || {
for _ in 0..100 {
*s.lock().unwrap() += 1;
}
}));
}Rust'ta veri mutex'in içinde durur; kilidi almadan veriye ulaşmanın yolu yoktur. Bu, "kilidi almayı unuttum" hatasını imkânsız kılar.
Kilit süresi ve deadlock
Guard'ı uzun tutmak diğer thread'leri bekletir. İki kilit farklı sırayla alınırsa iki thread birbirini sonsuza dek bekleyebilir (deadlock). Kurallar: kilidi kısa tut, kilit altında yavaş iş yapma, birden çok kilidi hep aynı sırayla al:
{
let mut veri = kilitli.lock().unwrap();
veri.push(1);
} // guard burada bırakılır, kilit açılır
yavas_islem(); // kilit tutulmadanRust veri yarışlarını önler, ama deadlock mantıksal bir hatadır ve derleyici onu yakalamaz.
Uygulama Paylaşılan sayaç
Arc<Mutex<i32>> sayacı 8 thread ile paylaş; her thread sayacı 100 kez artırsın. Tüm thread'leri join ettikten sonra son değeri yazdır.
Başlangıç kodu
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
// buraya yaz
}Örnek çözüm
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let sayac = Arc::new(Mutex::new(0));
let mut h = Vec::new();
for _ in 0..8 {
let s = Arc::clone(&sayac);
h.push(thread::spawn(move || {
for _ in 0..100 {
*s.lock().unwrap() += 1;
}
}));
}
for t in h {
t.join().unwrap();
}
println!("{}", *sayac.lock().unwrap());
}Beklenen çıktı
800
Soru ve cevaplar
Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.
1 <code>lock()</code> neden <code>Result</code> döndürür?
- Zaman aşımı için
- Gelenek
- Kilidi tutan bir thread panic verdiyse mutex "zehirlenir" (poisoned) Doğru cevap
- Kilit alınamayabilir
Açıklama: Zehirlenme, verinin yarım kalmış bir güncelleme yüzünden tutarsız olabileceği uyarısıdır.
2 Kilidi al
*s.____().unwrap() += 1;
*s.lock().unwrap() += 1;
Açıklama: Mutex::lock bir guard döndürür; guard üzerinden veri değiştirilir.
3 Kavram ve anlamı
| Kavram | Anlamı |
|---|---|
Mutex::lock() |
MutexGuard |
guard drop |
Kilit açılır |
poisoned |
Kilit sahibi panic verdi |
deadlock |
Karşılıklı bekleme |