CodeBlanks Logo Icon CodeBlanks

Özet - Eşzamanlılık

thread, Arc ve Mutex'i birleştirerek paralel bir sayaç yazarsın.

Eşzamanlılık özeti

thread::spawn sahiplenen (move) closure'larla thread başlatır; thread::scope ödünç almaya izin verir. Paylaşım için Arc, değiştirme için içine Mutex (tek erişim) ya da RwLock (çok okuyucu/tek yazıcı). Send ve Sync işaretçi trait'leri sayesinde veri yarışları derleme anında engellenir; deadlock ise mantıksal bir hatadır ve kilit sırasıyla önlenir.

Paralel kelime sayımı

Her metin ayrı bir thread'de sayılır, sonuç kilit altında tek seferde ortak haritaya eklenir:

let sayim = Arc::new(Mutex::new(HashMap::new()));
thread::scope(|s| {
    for metin in &metinler {
        let sayim = Arc::clone(&sayim);
        s.spawn(move || {
            let mut yerel: HashMap<String, usize> = HashMap::new();
            for k in metin.split_whitespace() {
                *yerel.entry(k.to_string()).or_insert(0) += 1;
            }
            let mut ortak = sayim.lock().unwrap();
            for (k, n) in yerel {
                *ortak.entry(k).or_insert(0) += n;
            }
        });
    }
});

Uygulama Paralel sayım

["elma armut", "elma", "armut kiraz elma"] metinlerini yukarıdaki gibi ayrı thread'lerde say. Sonucu bir vektöre topla, sırala ve {:?} ile yazdır.

Başlangıç kodu

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

fn main() {
    // buraya yaz
}

Örnek çözüm

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

fn main() {
    let metinler = ["elma armut", "elma", "armut kiraz elma"];
    let sayim = Arc::new(Mutex::new(HashMap::new()));
    thread::scope(|s| {
        for metin in &metinler {
            let sayim = Arc::clone(&sayim);
            s.spawn(move || {
                let mut yerel: HashMap<String, usize> = HashMap::new();
                for k in metin.split_whitespace() {
                    *yerel.entry(k.to_string()).or_insert(0) += 1;
                }
                let mut ortak = sayim.lock().unwrap();
                for (k, n) in yerel {
                    *ortak.entry(k).or_insert(0) += n;
                }
            });
        }
    });
    let mut v: Vec<(String, usize)> = sayim.lock().unwrap().clone().into_iter().collect();
    v.sort();
    println!("{:?}", v);
}

Beklenen çıktı

[("armut", 2), ("elma", 3), ("kiraz", 1)]

Soru ve cevaplar

Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.

1 Paralel kelime sayımında her thread'in kendi yerel HashMap'ini doldurup sonunda birleştirmesi neden daha hızlıdır?

  • Daha az bellek kullanır
  • Fark yoktur
  • Her kelimede ortak kilidi beklemek ortadan kalkar Doğru cevap
  • HashMap thread güvenli değildir

Açıklama: Kilit çekişmesi paralelliği öldürür; ortak durumu en aza indirmek ana kuraldır.

2 Ortak harita

Soru
let sayim = Arc::new(____::new(HashMap::new()));
Cevap
let sayim = Arc::new(Mutex::new(HashMap::new()));

Açıklama: Thread'ler arası değiştirilebilir paylaşım için Arc<Mutex<T>>.

3 Grubun özeti

Kavram Anlamı
thread::scope Ödünçlü thread
Mutex Tek erişim
RwLock Çok okuyucu
Send/Sync Derleme anı güvenlik

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