La biblioteca estándar de Rust ofrece los principales primitivos de sincronización para trabajar de manera segura con la multihilo:
AtomicBool, AtomicUsize, etc.) — operaciones de lectura/escritura sin bloqueos, a nivel de hardware;Ejemplo:
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!("Resultado: {}", *counter.lock().unwrap()); }
Pregunta: ¿Garantiza Rust que el uso de Mutex<T> elimina completamente los deadlocks mediante la comprobación en tiempo de compilación?
Respuesta: No. Rust asegura acceso seguro a los datos mediante propiedad y el comprobador de préstamos, pero no protege contra deadlocks a nivel del lenguaje. Los bloqueos muertos surgen lógicamente al violar el orden de adquisición de múltiples Mutex o su adquisición recursiva. Ejemplo:
use std::sync::Mutex; let lock1 = Mutex::new(0); let lock2 = Mutex::new(0); // Hilo 1: lock1 -> lock2, Hilo 2: lock2 -> lock1 ⇒ deadlock
Historia
Historia
Mutex<Option<T>> a RwLock<T>, sin tener en cuenta que el bloqueo escribible podía ser más prolongado que el bloqueo de lectura. En picos de carga, esto resultó en retrasos de procesamiento de hasta decenas de segundos debido a las colas en write.Historia
Los programadores intentaron economizar en hilos, "empujando" Arc<Mutex<_>> en cientos de hilos. Debido a los detalles del funcionamiento del programador y la reutilización de mutex, aparecieron sorprendentes esperas mutuas — ¡la productividad se redujo 5 veces!