0Pricing
Learn Rust Coding · Leçon

Déplacer des données dans des threads

Utilisez correctement les fermetures move.

Déplacer des données dans des threads est une leçon Learn Rust Coding gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Learn Rust Coding, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Learn Rust Coding comprend 4 leçons au total.

Les fermetures capturent l’environnement

Une fermeture transmise à thread::spawn peut utiliser des variables de la portée environnante. Par défaut, Rust les emprunte.

Cependant, un thread créé peut vivre plus longtemps que la fonction qui l’a créé ; un simple emprunt n’est donc pas sûr. Rust le refuse au moment de la compilation.

Le problème de l’emprunt

Si un thread emprunte une variable locale, le compilateur ne peut pas prouver que cette variable vivra assez longtemps. Le thread pourrait continuer à s’exécuter après la suppression de la variable.

Le code ci-dessous ne compile pas, car la fermeture ne fait qu’emprunter data.

use std::thread;

fn main() {
    let data = vec![1, 2, 3];
    // ERROR: closure may outlive `data`
    let h = thread::spawn(|| {
        println!("{:?}", data);
    });
    h.join().unwrap();
}

Le mot-clé move

Ajouter move avant la fermeture l’oblige à prendre possession des variables capturées. Celles-ci sont déplacées dans le thread.

Le thread possède alors les données, qui sont donc garanties de rester valides pendant toute sa durée de vie.

use std::thread;

fn main() {
    let data = vec![1, 2, 3];
    let h = thread::spawn(move || {
        println!("{:?}", data);
    });
    h.join().unwrap();
}

Le transfert de propriété

Une fois une valeur déplacée dans un thread, la portée d’origine ne peut plus l’utiliser. La propriété a été transférée.

Essayer d’utiliser data dans main après le déplacement provoquerait une erreur de compilation. Le thread est désormais l’unique propriétaire.

use std::thread;

fn main() {
    let data = vec![1, 2, 3];
    let h = thread::spawn(move || println!("{:?}", data));
    // println!("{:?}", data); // ERROR: value moved
    h.join().unwrap();
}

Déplacer des types Copy

Les types qui implémentent Copy, comme les entiers, sont copiés plutôt que déplacés. La fermeture reçoit sa propre copie.

Ainsi, après qu’une fermeture move a capturé un nombre, vous pouvez toujours utiliser l’original dans main.

use std::thread;

fn main() {
    let n = 42;
    let h = thread::spawn(move || {
        println!("thread sees {}", n);
    });
    println!("main still sees {}", n);
    h.join().unwrap();
}

Send : transfert sécurisé

Un type ne peut être déplacé dans un autre thread que s’il implémente le trait Send. Send signifie que le transfert de propriété entre threads est sûr.

La plupart des types sont automatiquement Send. Quelques-uns, comme Rc, ne le sont pas, et le compilateur refusera de les déplacer.

Rc n’est pas Send

Rc est un compteur de références utilisable avec un seul thread. Son compteur n’est pas protégé contre les mises à jour simultanées ; il n’est donc pas Send.

Essayer de déplacer un Rc dans un thread échoue à la compilation. Vous utiliserez Arc dans la leçon suivante.

use std::rc::Rc;
use std::thread;

fn main() {
    let r = Rc::new(5);
    // ERROR: `Rc<i32>` cannot be sent between threads safely
    let h = thread::spawn(move || println!("{}", r));
    h.join().unwrap();
}

Déplacer plusieurs valeurs

Une seule fermeture move peut capturer plusieurs variables à la fois. Elles sont toutes déplacées dans le thread.

C’est pratique lorsqu’un thread de travail a besoin à la fois d’une donnée d’entrée et d’une étiquette.

use std::thread;

fn main() {
    let label = String::from("sum");
    let nums = vec![1, 2, 3, 4];
    let h = thread::spawn(move || {
        let total: i32 = nums.iter().sum();
        println!("{} = {}", label, total);
    });
    h.join().unwrap();
}

Cloner avant de déplacer

Si le thread et la fonction principale ont tous deux besoin d’une valeur, clonez-la d’abord. Donnez un clone au thread et conservez l’autre.

Le clonage copie les données ; chaque partie possède donc une valeur indépendante.

use std::thread;

fn main() {
    let original = String::from("hello");
    let for_thread = original.clone();
    let h = thread::spawn(move || println!("thread: {}", for_thread));
    println!("main: {}", original);
    h.join().unwrap();
}

Renvoyer les données déplacées

Un thread qui possède des données déplacées peut les renvoyer et restituer la propriété au thread parent via join.

Ce modèle déplace les données à l’intérieur, les traite, puis déplace le résultat vers l’extérieur.

use std::thread;

fn main() {
    let mut v = vec![3, 1, 2];
    let h = thread::spawn(move || {
        v.sort();
        v
    });
    let sorted = h.join().unwrap();
    println!("{:?}", sorted);
}

Pourquoi move est nécessaire

Sans move, le vérificateur d’emprunts suppose que la fermeture emprunte les données. Comme les threads créés n’ont pas de durée de vie fixe liée à l’appelant, ces emprunts sont dangereux.

Le mot-clé move transforme les emprunts en transferts de propriété, ce qui satisfait l’exigence 'static de spawn.

Vérification rapide

Vérifiez votre compréhension du déplacement de données dans les threads.

Récapitulatif

Vous avez appris que les fermetures de threads doivent posséder les données qu’elles utilisent, ce qui s’obtient avec le mot-clé move.

Le déplacement transfère la propriété, tandis que les types Copy sont copiés. Le trait Send indique ce qu’il est sûr de transférer, et Rc n’est pas Send.

Vous allez maintenant partager des données entre threads avec Arc et Mutex.

Questions Fréquemment Posées

La leçon « Déplacer des données dans des threads » est-elle gratuite ?

Oui — le texte complet de « Déplacer des données dans des threads » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Learn Rust Coding, passe à CoddyKit PRO. Le cours Learn Rust Coding comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Déplacer des données dans des threads » ?

Utilisez correctement les fermetures move. Tu pratiques Learn Rust Coding avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Learn Rust Coding ?

Aucune expérience préalable n'est requise. Learn Rust Coding sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.

Combien de temps prend la leçon « Déplacer des données dans des threads » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Learn Rust Coding ?

Oui. Chaque leçon Learn Rust Coding inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Créer des threads
  2. Déplacer des données dans des threads
  3. Partager avec Arc et Mutex
  4. Rejoindre les threads et recueillir les résultats
← Retour à Learn Rust Coding