CodeBlanks Logo Icon CodeBlanks

Mutex<T>

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 tutulmadan

Rust 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

main.rs
use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    // buraya yaz
}

Örnek çözüm

main.rs
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

Soru
*s.____().unwrap() += 1;
Cevap
*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

İleri seviye bölümündeki tüm dersler