Históricamente, trabajar con la multihilo ha estado acompañado de fallos, condiciones de carrera y fugas, especialmente en el intercambio no controlado de memoria. Rust implementa el concepto de seguridad de hilos a nivel de tipos: un objeto solo se puede pasar a un hilo si implementa los traits necesarios (Send, Sync). Los hilos se crean a través de std::thread::spawn, y la comunicación entre ellos se realiza a través de canales o memoria compartida con mutación controlada (Mutex, Arc).
Problema: gestionar la sincronización manualmente es complicado y peligroso. Pasar objetos arbitrarios entre hilos sin una transferencia explícita de propiedad conduce a condiciones de carrera y caídas.
Solución: solo objetos que pueden ser movidos explícitamente (move) o compartidos a través de Arc, Mutex, así como canales de mensajes integrados (std::sync::mpsc, crossbeam). Esto minimiza los errores relacionados con el intercambio de datos sincrónico y asincrónico: la propiedad siempre es única.
Ejemplo de código:
use std::thread; use std::sync::mpsc; fn main() { let (tx, rx) = mpsc::channel(); thread::spawn(move || { tx.send(String::from("¡Hola desde el hilo!")).unwrap(); }); let received = rx.recv().unwrap(); println!("Recibido: {}", received); }
Características clave:
¿Se puede seguir utilizando un objeto en el hilo principal después de haberlo pasado a través de move?
No, tan pronto como el objeto es movido (por ejemplo, a un closure en thread::spawn), no se puede usar en el hilo padre, el compilador no permitirá compilar el código.
¿Se pueden pasar referencias mutables (&mut T) entre hilos?
No, una referencia mutable &mut T solo puede existir en una instancia, y el trait Send no está implementado para ella de forma predeterminada. Para trabajar con datos mutables se utiliza un envoltorio a través de Mutex/Arc.
¿Por qué no se puede usar Rc<T> para compartir propiedad entre hilos?
Rc<T> no implementa Sync y Send, ya que su contador interno no es seguro para hilos. Para uso thread-safe se utiliza Arc<T> (contador de referencias atómico).
// Comparación de Rc y Arc use std::sync::Arc; let x = Arc::new(5); // se puede clonar y compartir entre hilos
Un desarrollador decidió compartir una cadena entre hilos usando Rc<String>, coloca Rc dentro de thread::spawn. El código solo compila si se fuerza el casting a través de unsafe, después de lo cual la aplicación puede fallar o funcionar con datos corruptos.
Ventajas:
Desventajas:
Se utiliza Arc<String> + Mutex<String> para acceso seguro, o la transferencia de mensajes a través de un canal, sin propiedad compartida.
Ventajas:
Desventajas: