Les Threads en Rust

Introduction aux Threads en Rust

Les threads en Rust permettent d'exécuter plusieurs parties d'un programme simultanément. L'utilisation des threads peut considérablement diminuer le temps requis pour effectuer des tâches pouvant être exécutées en parallèle. La bibliothèque standard de Rust fournit un module de thread qui permet aux développeurs de gérer les threads.

Création d'un Thread

Pour créer un nouveau thread, on utilise la fonction thread::spawn(). Voici un exemple :

use std::thread;
use std::time::Duration;

fn main() {
    thread::spawn(|| {
        for i in 1..10 {
            println!("Thread créé : {}", i);
            thread::sleep(Duration::from_millis(3));
        }
    });

    for i in 1..4 {
        println!("Thread principal : {}", i);
        thread::sleep(Duration::from_millis(1));
    }
}

Dans cet exemple, le thread créé affiche des nombres de 1 à 9, tandis que le thread principal affiche des nombres de 1 à 3. Les durées de thread::sleep() contrôlent le rythme d'affichage. Il est important de noter que le thread créé dans cet exemple n'affiche que jusqu'à 3, car le thread principal termine son exécution.

Gestion des Join Handles

Lorsqu'on appelle la fonction spawn, cela retourne un JoinHandle. On peut stocker ce JoinHandle dans une variable et appeler la méthode join() pour s'assurer que le thread créé a terminé son exécution. Voici une autre version de l'exemple précédent :

use std::thread;
use std::time::Duration;

fn main() {
    let join_handle = thread::spawn(|| {
        for i in 1..10 {
            println!("Thread créé : {}", i);
            thread::sleep(Duration::from_millis(3));
        }
    });

    for i in 1..4 {
        println!("Thread principal : {}", i);
        thread::sleep(Duration::from_millis(1));
    }
    join_handle.join().unwrap();
}

Dans ce cas, les threads créés atteignent 9 même lorsque le thread principal a complété son exécution.

Utilisation des Closures avec move dans les Threads

Pour transmettre en toute sécurité la propriété d'une variable d'un thread à un autre, on peut utiliser le mot-clé move dans la fonction thread::spawn(). Voici un exemple sans utiliser move :

use std::thread;

fn main() {
    let salutation = String::from("bonjour");
    let handle = thread::spawn(|| {
        println!("{}", salutation);
    });
    handle.join().unwrap();
}

Ce programme échouera à la compilation et affichera un message d'erreur car Rust ne peut pas garantir la durée de vie de salutation dans le thread créé. Pour résoudre ce problème, on peut passer le mot-clé move :

use std::thread;

fn main() {
    let salutation = String::from("bonjour");
    let handle = thread::spawn(move || {
        println!("{}", salutation);
    });
    handle.join().unwrap();
}

Cette fois, l'exécution affichera :

bonjour