Skip to content
Zurück zu den Lernmaterialien

Modul 12 — Concurrency & Threads

6. September 2026~3 min read
Lektion von 0/ abgeschlossen
Modul 12 — Concurrency & Threads

Threads: spawn, move, join

Ein Programm kann Arbeit auf mehrere Kerne verteilen: Threads. Der Start ist ein Funktionsaufruf mit einer Closure:

use std::thread;

fn main() {
    let daten = vec![1, 2, 3, 4];

    let handle = thread::spawn(move || {
        let summe: i32 = daten.iter().sum();
        summe * 10
    });

    println!("Ergebnis: {}", handle.join().unwrap());
}

Drei Bausteine: spawn startet die Closure auf einem neuen Thread, move übergibt die gefangenen Daten als Besitz (nicht als Leihe — der Thread könnte den erzeugenden Scope überleben, also würde jede Referenz baumeln), und join() wartet auf das Ende und liefert das Ergebnis. Vergisst du join, endet main möglicherweise zuerst — und der Prozess nimmt den Thread mit ins Grab, bevor er fertig war.

Warum move bei Threads Pflicht ist

  • Der Thread kann länger leben als die erzeugende Funktion
  • Geliehene Daten könnten dangling werden — der Compiler verbietet das
  • move überträgt Besitz: die Daten gehören ab jetzt dem Thread
  • Das ist keine Einschränkung, sondern die Datenrennen-Prävention

📝 Schnellprüfung

Was passiert, wenn main endet, während ein Thread noch läuft?

Übung: spawn + join

🧩 Übung m12-l1-e1

🔮 Vorhersage: Was passiert beim Ausführen?

Editor wird geladen…
KI-Tutor (sokratisch — keine Komplettlösungen)

✅ Wichtige Erkenntnisse

Haken setzen, um deinen Lernfortschritt zu markieren:

    Lektion von 0/ abgeschlossen
    Modul 12 — Concurrency & Threads

    Channels: Kommunikation statt Teilung

    Der sauberste Weg, Threads Daten austauschen zu lassen: Channels — eine Einbahnstraße für Nachrichten. Go hat den Spruch geprägt: "Do not communicate by sharing memory; share memory by communicating."

    use std::sync::mpsc;
    use std::thread;
    
    fn main() {
        let (tx, rx) = mpsc::channel();
    
        thread::spawn(move || {
            for n in 1..=3 {
                tx.send(n * n).unwrap();
            }
            drop(tx);
        });
    
        while let Ok(wert) = rx.recv() {
            println!("{wert}");
        }
    }
    

    mpsc heißt: multiple producers, single consumer — viele Sender (Sender clonen), ein Empfänger. send überträgt Besitz der Nachricht, recv wartet blockierend. Und das Ende ist im Typ verankert: gehen alle Sender verloren, liefert recv ein Err — der while-let-Loop endet von selbst. Kein Polling, keine Magic-Values: die Kanal-Schließung IST ein Wert.

    📝 Schnellprüfung

    Warum endet der while-let-Loop über rx.recv() automatisch, wenn der Sender drop't?

    Übung: der Quadrat-Kanal

    🧩 Übung m12-l2-e1

    🔮 Vorhersage: Was passiert beim Ausführen?

    Editor wird geladen…
    KI-Tutor (sokratisch — keine Komplettlösungen)

    ✅ Wichtige Erkenntnisse

    Haken setzen, um deinen Lernfortschritt zu markieren:

      Lektion von 0/ abgeschlossen
      Modul 12 — Concurrency & Threads

      Geteilter Zustand: Mutex + Arc

      Manchmal willst du Daten nicht kopieren oder schicken, sondern wirklich teilen. Dann braucht es zwei Teile: einen Schloss-Mechanismus und einen thread-sicheren Besitz.

      use std::sync::{Arc, Mutex};
      use std::thread;
      
      fn main() {
          let zaehler = Arc::new(Mutex::new(0u32));
      
          let mut handles = Vec::new();
          for _ in 0..4 {
              let z = Arc::clone(&zaehler);
              handles.push(thread::spawn(move || {
                  *z.lock().unwrap() += 10;
              }));
          }
          for h in handles {
              h.join().unwrap();
          }
          println!("Zähler: {}", *zaehler.lock().unwrap());
      }
      

      Mutex ist das Schloss: lock() gibt dir einen Guard — nur über ihn erreichst du die Daten, und beim Drop des Guards gibt er das Schloss frei. Das Schloss-Umgehen ist unmöglich, die Daten liegen ja EINGESPERRT im Mutex. Arc ist Rc mit atomarem Zähler — der einzige Grund, warum dieselbe Struktur über Threads geteilt werden darf.

      Beides zusammen ist die Standard-Antwort auf "vier Threads, ein Zähler" — und der Compiler erzwingt die Kombination: Rc-Container verweigert er mit E0277, ein Mutex ohne Teilung wäre sinnlos.

      Fearless Concurrency konkret

      • Datenrennen (data races) sind in safe Rust Compile-Fehler, keine crash bugs
      • Send/Sync-Traits beschreiben, welche Typen thread-überqueren dürfen
      • MutexGuard = scoped locking: keine vergessenen unlocks
      • Deadlock-Risiko bleibt — aber Rennen verhindert der Compiler

      Übung: der geteilte Zähler

      🧩 Übung m12-l3-e1

      🔮 Vorhersage: Was passiert beim Ausführen?

      Editor wird geladen…
      KI-Tutor (sokratisch — keine Komplettlösungen)

      ✅ Wichtige Erkenntnisse

      Haken setzen, um deinen Lernfortschritt zu markieren:

        Lektion von 0/ abgeschlossen
        Modul 12 — Concurrency & Threads

        Mini-Projekt: die parallele Summe

        Der Abschluss: eine Million Zahlen, zwei Kerne, eine Antwort. Das Szenario:

        🏢 Praxis-Szenario: Die Auswertung, die ewig dauert

        Dein Team wertet riesige Messreihen aus — seriell, in einer Schleife, sekundenlang. Auf einem Mehrkern-Rechner arbeitet dabei 1 von 8 Kernen. Der Vorschlag: die Datenreihe halbieren und beide Hälften parallel summieren. Aber Vorsicht — naive Ansätze mit geteilten Variablen enden in Datenrennen oder Compile-Fehlern. Genau das soll die Lösung vermeiden, nicht nur vermeiden lassen.

        🧩 Übung m12-l4-e1

        🔮 Vorhersage: Was passiert beim Ausführen?

        Editor wird geladen…
        KI-Tutor (sokratisch — keine Komplettlösungen)

        Was du in Modul 12 geschafft hast

        • Threads mit spawn/move/join — Besitz als Ticket in den Nebenlauf
        • Channels: Nachrichten mit Besitz-Übergabe, Ende im Typ verankert
        • Mutex + Arc für den unvermeidlichen geteilten Zustand
        • Parallelisierung durch Aufteilen statt Synchronisieren

        ✅ Wichtige Erkenntnisse

        Haken setzen, um deinen Lernfortschritt zu markieren:

          Modul-Checkpoint

          Checkpoint: Modul 12

          Bestehensgrenze: 80 %. Der Versuch wird bewertet und zählt für das Modul-Gate.

          Bereit, dein Wissen zu testen?

          Probiere unsere Übungsprüfungen mit Hunderten von realistischen Fragen aus.

          Üben starten →

          This site uses essential cookies for Stripe payments. No tracking cookies.