0Pricing
Learn Rust Coding · Lektion

Daten in Threads verschieben

Verwenden Sie move-Closures korrekt.

Daten in Threads verschieben ist eine kostenlose Learn Rust Coding-Lektion auf CoddyKit. Dies ist Lektion 2 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Learn Rust Coding-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Learn Rust Coding-Kurs umfasst insgesamt 4 Lektionen.

Closures erfassen ihre Umgebung

Eine an thread::spawn übergebene Closure kann Variablen aus dem umgebenden Gültigkeitsbereich verwenden. Standardmäßig leiht Rust diese Variablen aus.

Ein gestarteter Thread kann jedoch länger leben als die Funktion, die ihn erstellt hat. Eine einfache Ausleihe wäre daher nicht sicher. Rust weist dies bereits zur Kompilierzeit zurück.

Das Ausleihproblem

Wenn ein Thread eine lokale Variable ausleiht, kann der Compiler nicht beweisen, dass die Variable lange genug lebt. Der Thread könnte weiterlaufen, nachdem die Variable verworfen wurde.

Der folgende Code wird nicht kompiliert, weil die Closure data nur ausleiht.

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();
}

Das Schlüsselwort move

Wenn Sie vor der Closure move hinzufügen, übernimmt sie den Besitz der erfassten Variablen. Diese werden in den Thread verschoben.

Nun besitzt der Thread die Daten, sodass garantiert ist, dass sie während der Lebensdauer des Threads gültig bleiben.

use std::thread;

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

Besitz wird herausübertragen

Sobald ein Wert in einen Thread verschoben wurde, kann der ursprüngliche Gültigkeitsbereich ihn nicht mehr verwenden. Der Besitz wurde übertragen.

Wenn Sie data in main nach dem Verschieben verwenden, führt dies zu einem Kompilierfehler. Der Thread ist nun der alleinige Besitzer.

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();
}

Copy-Typen verschieben

Typen, die Copy implementieren, etwa Ganzzahlen, werden kopiert statt verschoben. Die Closure erhält eine eigene Kopie.

Nach dem Erfassen einer Zahl durch eine move-Closure können Sie das Original daher weiterhin in main verwenden.

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: Sicher übertragbar

Ein Typ kann nur dann in einen anderen Thread verschoben werden, wenn er das Trait Send implementiert. Send bedeutet, dass der Besitz sicher zwischen Threads übertragen werden kann.

Die meisten Typen sind automatisch Send. Einige wenige, etwa Rc, sind es nicht, und der Compiler weist ihren Transfer zurück.

Rc ist nicht Send

Rc ist ein Referenzzähler für einzelne Threads. Sein Zähler ist nicht gegen gleichzeitige Aktualisierungen geschützt, daher ist Rc nicht Send.

Der Versuch, ein Rc in einen Thread zu verschieben, führt zu einem Kompilierfehler. In der nächsten Lektion verwenden Sie stattdessen Arc.

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();
}

Mehrere Werte verschieben

Eine einzelne move-Closure kann mehrere Variablen gleichzeitig erfassen. Alle werden in den Thread verschoben.

Das ist nützlich, wenn ein Worker sowohl Eingabedaten als auch eine Bezeichnung benötigt.

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();
}

Vor dem Verschieben klonen

Wenn sowohl der Thread als auch die Hauptfunktion einen Wert benötigen, klonen Sie ihn zuerst. Übergeben Sie einen Klon an den Thread und behalten Sie den anderen.

Beim Klonen werden die Daten kopiert, sodass jede Seite einen unabhängigen Wert besitzt.

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();
}

Verschobene Daten zurückgeben

Ein Thread, der verschobene Daten besitzt, kann sie zurückgeben und den Besitz über join an den übergeordneten Thread übertragen.

Bei diesem Muster werden Daten hineingeschoben, verarbeitet und anschließend als Ergebnis wieder herausgeschoben.

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);
}

Warum move erforderlich ist

Ohne move nimmt der Borrow Checker an, dass die Closure ausleiht. Da gestartete Threads keine an den Aufrufer gebundene feste Lebensdauer besitzen, wären solche Ausleihvorgänge unsicher.

Das Schlüsselwort move wandelt Ausleihvorgänge in Besitzübertragungen um und erfüllt damit die 'static-Anforderung von spawn.

Kurze Überprüfung

Testen Sie Ihr Verständnis vom Verschieben von Daten in Threads.

Zusammenfassung

Sie haben gelernt, dass Thread-Closures die von ihnen verwendeten Daten besitzen müssen, was mit dem Schlüsselwort move erreicht wird.

Beim Verschieben wird der Besitz übertragen, während Copy-Typen kopiert werden. Das Trait Send kennzeichnet, was sicher übertragen werden kann, und Rc ist nicht Send.

Als Nächstes teilen Sie Daten zwischen Threads mithilfe von Arc und Mutex.

Häufig gestellte Fragen

Ist die Lektion „Daten in Threads verschieben“ kostenlos?

Ja — der vollständige Text von „Daten in Threads verschieben“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Learn Rust Coding-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Learn Rust Coding-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Daten in Threads verschieben“?

Verwenden Sie move-Closures korrekt. Du übst Learn Rust Coding mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Learn Rust Coding zu starten?

Keine Vorkenntnisse erforderlich. Learn Rust Coding auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 4.

Wie lange dauert die Lektion „Daten in Threads verschieben“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Learn Rust Coding-Lektion Code schreiben und ausführen?

Ja. Jede Learn Rust Coding-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Threads erzeugen
  2. Daten in Threads verschieben
  3. Mit Arc und Mutex teilen
  4. Threads verbinden und Ergebnisse sammeln
← Zurück zu Learn Rust Coding