ProgramlamaBackend Geliştirici

Rust standart kütüphanesi hangi thread senkronizasyon yöntemlerini sunar? Aralarında nasıl seçim yapılır ve hangi "ince noktaları" dikkate almak gerekir?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap

Rust standart kütüphanesi, çok iş parçacıklı çalışmada güvenli bir şekilde çalışmak için temel senkronizasyon primitiflerini sunar:

  • Mutex — birden fazla iş parçacığının verilere erişimi için karşıt hariç tutma (mutual exclusion) sağlar;
  • RwLock — aynı anda birden fazla okuyucu (read) ama sadece bir yazıcı (write) olmasına izin verir;
  • Condvar — bir olaya göre iş parçacıklarını uyandırmak için şart değişkeni primitifidir;
  • Atomic tipler (AtomicBool, AtomicUsize vb.) — kilit olmadan okuma/yazma işlemleri, donanım seviyesinde;
  • Arc (Atomic Reference Counted) — nesnelerin ortak sahibi olmak için iş parçacığı güvenliği ile referans sayımı.

Seçim:

  • Eğer yalnızca okuma gerekiyorsa — RwLock kullanın (Mutex'ten daha verimli).
  • Tek bir iş parçacığının senkronize erişimi için — Mutex.
  • Sinyal ile senkronizasyon için (örneğin, "yeni bir öğeyi beklemek") — Condvar.
  • Atomik sayaçlar/bayraklar için — Atomic.
  • Ortak sahiplik (çok iş parçacıklı) için — Arc.

Örnek:

use std::sync::{Arc, Mutex}; use std::thread; fn main() { let counter = Arc::new(Mutex::new(0)); let mut handles = vec![]; for _ in 0..10 { let counter = Arc::clone(&counter); let handle = thread::spawn(move || { let mut num = counter.lock().unwrap(); *num += 1; }); handles.push(handle); } for handle in handles { handle.join().unwrap(); } println!("Sonuç: {}", *counter.lock().unwrap()); }

İkna Edici Soru

Soru: Rust, Mutex<T> kullanmanın, derleme aşamasında yapılan kontrol sayesinde deadlock'ları tamamen ortadan kaldırdığını garanti eder mi?

Cevap: Hayır. Rust, sahiplik ve borrow-checker aracılığıyla verilere güvenli erişim sağlar, ancak dil düzeyinde deadlock'lara karşı koruma sağlamaz. Deadlock'lar, birkaç Mutex'in ele geçirilme sırasının ihlal edilmesi veya bunların özyinelemeli ele geçirilmesi gibi mantıksal nedenlerle ortaya çıkar. Örnek:

use std::sync::Mutex; let lock1 = Mutex::new(0); let lock2 = Mutex::new(0); // İş Parçacığı 1: lock1 -> lock2, İş Parçacığı 2: lock2 -> lock1 ⇒ deadlock

Tarih

Veri akış işleme projesi rastgele "dondurmalar" yaşadı. Geliştiricilerin kesin bir ele geçirme sırası olmaksızın iç içe geçmiş Mutex'ler (Mutex içinde Mutex) kullandığı ortaya çıktı, bu da yalnızca sürecin zorla sonlandırılmasıyla çözülmeyi gerektiren deadlock'lara yol açıyordu.

Tarih

Büyük bir hizmette, Mutex<Option<T>>'dan RwLock<T>'a büyük çapta geçiş yapıldı ama yazılabilir kilidin okuma kilidinden daha uzun olabileceği dikkate alınmadı. Pik yük altında, yazma için bekleme kuyrukları nedeniyle işleme gecikmeleri onlarca saniye sürdü.

Tarih

Programcılar, iş parçacıklarında tasarruf etmeye çalıştı, yüzlerce iş parçacığına Arc<Mutex<_>> "itip" gönderdiler. Planlayıcının çalışması ve mutex'in yeniden kullanımı üzerindeki ince noktalardan dolayı şaşırtıcı karşıt beklentiler ortaya çıktı — verimlilik 5 kat azaldı!