CodeBlanks Logo Icon CodeBlanks

Arc<T>

Arc<T> ile iş parçacıkları arasında veri paylaşırsın.

Arc<T>

Arc<T> salt okunur verinin thread'ler arasında paylaşılmasını sağlar; değiştirme gerekiyorsa içine Mutex/RwLock konur. Büyük bir veriyi kopyalamadan parçalara bölüp her parçayı ayrı bir thread'e vermek tipik bir kullanımdır:

let veri: Arc<Vec<u32>> = Arc::new((1..=9).collect());
let tutucular: Vec<_> = (0..3)
    .map(|i| {
        let v = Arc::clone(&veri);
        thread::spawn(move || v[i * 3..i * 3 + 3].iter().sum::<u32>())
    })
    .collect();

Her thread yalnızca 8 baytlık bir işaretçi kopyası alır; vektörün kendisi tek bir kez bellekte durur.

Parçalara bölme

chunks(n) dilimi n'lik parçalara böler. Parça sayısını çekirdek sayısına göre seçmek iyi bir başlangıçtır: std::thread::available_parallelism().

let parca_boyu = veri.len().div_ceil(4);
for parca in veri.chunks(parca_boyu) {
    // her parça bir thread'e
}

Gerçek projelerde bu işi rayon crate'i tek satırda yapar: veri.par_iter().sum().

Uygulama Paralel parça toplamları

Arc<Vec<u32>> içinde 1'den 9'a kadar sayıları paylaş. Üç thread her biri üç elemanlık bir parçayı toplasın. Parça toplamlarını ve genel toplamı boşlukla yazdır.

Başlangıç kodu

main.rs
use std::sync::Arc;
use std::thread;

fn main() {
    // buraya yaz
}

Örnek çözüm

main.rs
use std::sync::Arc;
use std::thread;

fn main() {
    let veri: Arc<Vec<u32>> = Arc::new((1..=9).collect());
    let tutucular: Vec<_> = (0..3)
        .map(|i| {
            let v = Arc::clone(&veri);
            thread::spawn(move || v[i * 3..i * 3 + 3].iter().sum::<u32>())
        })
        .collect();
    let parcalar: Vec<u32> = tutucular.into_iter().map(|h| h.join().unwrap()).collect();
    let toplam: u32 = parcalar.iter().sum();
    println!("{:?} {}", parcalar, toplam);
}

Beklenen çıktı

[6, 15, 24] 45

Soru ve cevaplar

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

1 Aynı işi kopyasız yapmanın <code>Arc</code> dışındaki yolu nedir?

  • thread::scope ile dilimleri ödünç vermek Doğru cevap
  • static mut
  • Rc
  • clone

Açıklama: Veri yalnızca bu hesap süresince gerekiyorsa scope daha basittir; thread'ler fonksiyondan uzun yaşayacaksa Arc gerekir.

2 İşaretçiyi kopyala

Soru
let v = Arc::____(&veri);
thread::spawn(move || v.len());
Cevap
let v = Arc::clone(&veri);
thread::spawn(move || v.len());

Açıklama: Arc::clone yalnızca sayacı artırır, veriyi kopyalamaz.

3 Araç ve kullanım

Kavram Anlamı
Arc<T> Salt okunur paylaşım
Arc<Mutex<T>> Değiştirilebilir paylaşım
thread::scope Geçici ödünç
rayon Paralel yineleyici

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