Die Standardbibliothek von Rust bietet die grundlegenden Synchronisierungsprimitive für sicheres Arbeiten mit Multithreading:
AtomicBool, AtomicUsize usw.) — Lese-/Schreiboperationen ohne Sperren auf Hardwareebene;Beispiel:
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!("Result: {}", *counter.lock().unwrap()); }
Frage: Garantiert Rust, dass die Verwendung von Mutex<T> vollständig von Deadlocks befreit, durch Überprüfung zur Kompilierzeit?
Antwort: Nein. Rust gewährleistet einen sicheren Zugriff auf Daten durch Besitz und Borrow-Checker, schützt jedoch nicht auf Sprachebene vor Deadlocks. Deadlocks entstehen rein logisch durch das Brechen der Reihenfolge beim Erwerb mehrerer Mutex oder deren rekursiven Erwerb. Beispiel:
use std::sync::Mutex; let lock1 = Mutex::new(0); let lock2 = Mutex::new(0); // Thread 1: lock1 -> lock2, Thread 2: lock2 -> lock1 ⇒ deadlock
Geschichte
Geschichte
Mutex<Option<T>> zu RwLock<T>, ohne zu berücksichtigen, dass das schreibbare Lock länger dauern kann als das Leselock. Bei Spitzenlast führte dies zu Verarbeitungsverzögerungen von bis zu Sekunden aufgrund von Warteschlangen beim Schreiben.Geschichte
Programmierer versuchten, bei Threads zu sparen, und "drückten" Arc<Mutex<_>> in Hunderte von Threads. Aufgrund der Feinheiten der Planerarbeit und der Wiederverwendung von Mutex traten erstaunliche gegenseitige Erwartungen auf — die Leistung verringerte sich um das Fünffache!