yoklateknik mülakat

Backend Rs Concurrency Send Sync Mülakat Soruları

75 doğrulanmış Backend Rs Concurrency Send Sync mülakat sorusu — cevaplarıyla çöz, açıklamalarıyla öğren, gerçek simülasyonda kendini test et.

Gerçek simülasyonu dene →

Örnek sorular

Rs Concurrency Send SyncZorluk 1
fn main() {
    let name = String::from("worker");
    let h = std::thread::spawn(|| println!("{}", name));
    h.join().unwrap();
}

Bu kod derlendiğinde ne olur?
  • aDerlenir ve thread zamanlanınca worker yazdırır
  • bDerlenir, ama name thread çalışmadan düşebileceği için boş string basabilir
  • cE0373: closure main'den uzun yaşayabilir ama name'i ödünç alıyor; move şart
  • dE0382: name closure'a taşınıp sonra join tarafından yeniden kullanılıyor
Açıklama:thread::spawn 'static bir closure ister: yeni thread main'in stack çerçevesi gittikten sonra da çalışıyor olabilir, bu yüzden closure yerel bir değişkeni ödünç tutamaz. Derleyici E0373 verir ve move || önerir; bu, name'in sahipliğini closure'a aktarır. Burada çalışma zamanı yolu yoktur, program hiç derlenmez.
Rs Concurrency Send SyncZorluk 1
use std::rc::Rc;
fn main() {
    let r = Rc::new(5);
    let h = std::thread::spawn(move || println!("{}", r));
    h.join().unwrap();
}

Sonuç nedir?
  • aDerlenir ve 5 yazdırır; move Rc'yi thread'e verir
  • bE0277: Rc<i32> thread'ler arasında güvenle gönderilemez
  • cDerlenir, sonra atomik olmayan sayaca iki thread dokununca çalışma zamanında panic olur
  • dE0382: r closure'a taşındıktan sonra kullanılıyor
Açıklama:Rc atomik olmayan bir referans sayacı kullanır, bu yüzden standart kütüphane onu !Send işaretler. thread::spawn F: Send ister; closure r'yi değerle yakaladığı için closure'ın tamamı !Send olur ve derleyici E0277 ile durur. Mesaj birebir "cannot be sent between threads safely" der. Arc bunun thread-güvenli karşılığıdır ve derlenirdi.
Rs Concurrency Send SyncZorluk 3
use std::cell::Cell;
use std::sync::Arc;
fn main() {
    let c = Arc::new(Cell::new(1));
    let c2 = Arc::clone(&c);
    std::thread::spawn(move || c2.set(2)).join().unwrap();
    println!("{}", c.get());
}

Derleyici ne der?
  • aHiçbir şey; derlenir ve iki thread arasındaki kayıp güncelleme yüzünden 1 yazdırır
  • bHiçbir şey; derlenir ve join sonrası 2 yazdırır
  • cE0277: Arc<Cell<i32>> gönderilemez, zira Arc yalnızca Sync'tir, Send değildir
  • dE0277: Cell<i32> thread'ler arasında güvenle paylaşılamaz
Açıklama:Arc<T> yalnız T: Send + Sync iken Send'dir, çünkü her klon aynı T'ye başka bir thread'den ulaşabilir. Cell paylaşılan referans üzerinden senkronizasyonsuz değişikliğe izin verir, bu yüzden !Sync'tir. Hata Cell<i32>'yi adlandırır ve "shared" sözcüğünü kullanır; bu Sync ihlalinin ifadesidir, Send ihlalinde "sent" der. Değeri Mutex'e sarmak ya da AtomicI32 kullanmak sorunu çözer.
Rs Concurrency Send SyncZorluk 2
fn main() {
    let v = vec![1, 2, 3];
    let mut total = 0;
    std::thread::scope(|s| {
        s.spawn(|| { total = v.iter().sum(); });
    });
    println!("{} {:?}", total, v);
}

Ne yazdırılır?
  • aHiçbir şey; closure v ve totalmove olmadan ödünç aldığı için E0373 verilir
  • b0 [1, 2, 3], çünkü total scoped thread işini bitirmeden okunur
  • cHiçbir şey; total hem closure hem println! tarafından mutable ödünç alındığı için E0499 verilir
  • d6 [1, 2, 3]; scope dönmeden önce thread'lerini join eder
Açıklama:thread::scope, içinde açılan her thread'in scope dönmeden önce join edilmiş olacağını garanti eder. Scoped closure'ların v ve total gibi 'static olmayan veriyi ödünç alabilmesini sağlayan tam da bu garantidir. Scope sonrasında total 6'dır ve v dokunulmamıştır. Düz thread::spawn API'si bunu sunamaz, bu yüzden 'static yakalama ister.
Rs Concurrency Send SyncZorluk 1
fn main() {
    let h = std::thread::spawn(|| {
        panic!("boom");
    });
    let r = h.join();
    println!("is_err={}", r.is_err());
    println!("main continues");
}

Çalışma zamanında ne olur?
  • aPanic join üzerinden yayılır, main hiçbir şey yazdıramadan panic olur
  • bPanic mesajı stderr'e gider; ardından is_err=true ve main continues yazdırılır, çünkü panic yalnızca kendi thread'ini unwind eder
  • cSpawn edilen thread panic olduğu anda tüm süreç abort eder
  • dis_err=false yazdırılır; thread içindeki panic normal dönüş sayılır
Açıklama:Panic yalnızca gerçekleştiği thread'i unwind eder. Spawn edilen thread'in panic hook'u stderr'e "thread '<unnamed>' panicked" basar, ama main çalışmaya devam eder. JoinHandle::join Result<T, Box<dyn Any + Send>> döndürür; Err varyantı panic yükünü taşır, bu yüzden is_err=true yazdırılır ve akış sürer.
Rs Concurrency Send SyncZorluk 2
use std::sync::{Arc, Mutex};
fn main() {
    let data = Arc::new(Mutex::new(0));
    let mut hs = vec![];
    for _ in 0..3 {
        hs.push(std::thread::spawn(move || {
            *data.lock().unwrap() += 1;
        }));
    }
    for h in hs { h.join().unwrap(); }
}

Bu kod neden derlenmez?
  • aMutex<i32> Send olmadığı için closure thread::spawn'a gidemez
  • b+= mutable bir guard ister, ama lock() değere yalnızca paylaşılan referans döndürür
  • cdata ilk iterasyonda closure'a taşınır; sonrakinde E0382 verilir
  • dArc bir move closure tarafından yakalanamaz; main dışında klonlanmalıdır
Açıklama:move closure data'nın sahipliğini alır. Closure döngü içinde yaratıldığı için ikinci iterasyon zaten taşınmış bir değeri yeniden taşımaya çalışır ve derleyici E0382 raporlar ("value moved into closure here, in previous iteration of loop"). Deyimsel çözüm her iterasyonun başında let data = Arc::clone(&data); yazmaktır; böylece her thread paylaşılan mutex'e kendi tutamacıyla sahip olur.

3750 soruluk Backend bankasında kendini sına.

Mülakata başla