En Rust, il n'y a pas de collecteur d'ordures classique, donc pour gérer la possession de structures complexes, on utilise des smart pointers. Les plus couramment utilisés sont :
Box<T> — alloue de la mémoire pour un objet dans le tas et en transfère la possession. Utilisé pour les cas où la taille des données n'est pas connue au moment de la compilation ou lorsqu'une ressource déplaçable mais unique est nécessaire.
Rc<T> (Reference Counted) — compte des références, permettant à plusieurs variables de « partager » la possession de données immuables (uniquement dans un contexte monothread).
Arc<T> (Atomic Reference Counted) — implémente également le comptage de références, mais de manière atomique ; son utilisation est autorisée dans des programmes multithread.
RefCell<T> — fournit une possession « intérieure mutable » au moment de l'exécution, permettant de modifier le contenu même à travers une référence immuable, mais uniquement dans un seul thread (non sécurisé pour les threads!).
Exemple :
use std::rc::Rc; let a = Rc::new(vec![1,2,3]); let b = Rc::clone(&a); // Maintenant, a et b sont des propriétaires des mêmes données
Peut-on utiliser Rc<T> dans du code multithread, si tous les threads ne font que lire les données ? Expliquez.
Réponse : Non, on ne peut pas ! Bien que Rc<T> permette uniquement l'accès immuable aux données, le conteneur lui-même Rc<T> n'est pas sécurisé pour les threads, car le compteur de références interne n'est pas protégé contre les conditions de course. Pour cela, Arc<T> est prévu — son compteur interne est sécurisé pour les threads.
Exemple :
// Le code suivant ne se compilera pas ! use std::thread; use std::rc::Rc; let five = Rc::new(5); for _ in 0..10 { let five = Rc::clone(&five); thread::spawn(move || { println!("{}", five); }); }
Histoire
Histoire
Histoire
Dans un module de logique métier, ils ont utilisé RefCell<T> pour organiser un accès mutable aux données, qui étaient également transmises par Arc<T> entre les threads. Mais tenter de combiner RefCell<T> et Arc<T> a conduit à des conditions de course et à une panique lors de l'exécution. Pour une variante sécurisée pour les threads, ils auraient dû utiliser Mutex<T> ou RwLock<T> au lieu de RefCell<T>.