R

ReflexKR

Reflex-Dokumentation

Nebenläufigkeit in der Nachtküche

·

Kursüberblick

1

Die Schlange am ersten Abend: Nebenläufigkeit und Parallelität

2

Mehr Köche einstellen: Grundlagen von threading

3

Die Zahl auf der Tafel stimmt nicht: Race Conditions und Lock

4

Nur drei Herdplatten: Synchronisationswerkzeuge

5

Messer und Bretter: Deadlock

6

Die Bonschiene: queue

7

Leihköche: concurrent.futures

8

Warum der Teig nicht schneller wird: der GIL und Parallelität

9

Eine Servicechefin für alle Tische: erste Schritte mit asyncio

10

Die Gruppenreservierung platzt: strukturierte Nebenläufigkeit

11

Der Gastraum steht still: blockierende Aufrufe und Kombinieren

12

Die Nacht der Kritikerin: alles zusammen

Nebenläufigkeit in der Nachtküche
Lektion 1

Zeit 0:00–0:50

Die Schlange am ersten Abend: Nebenläufigkeit und Parallelität

Der Bon für heute Nacht

#01 · Erste Nacht

Die Schlange am ersten Abend

Problem

Kaum ist die Tür offen, stehen acht Gruppen im Lokal. Du stehst allein am Herd und machst eine Bestellung nach der anderen. Während die Suppe kocht, stehst du einfach daneben und wartest.

Ziel

Acht Bestellungen in unter einer Sekunde rausschicken.

Nachtlokal Dongsi

Eröffnungsabend, zehn Uhr. Kaum ist die Tür offen, strömen die Gäste herein. Du setzt die Suppe für die erste Bestellung auf und bleibst am Topf stehen, bis sie kocht. Nach drei Minuten geht die erste Schüssel raus, dann fängst du mit der zweiten Bestellung an.

Chefin Yoon Seoyeon schaut auf ihren Timer. „Was haben deine Hände gemacht, während die Suppe kochte? Nichts. Das ist das Problem heute Nacht.“

1-1. 0,3 Sekunden pro Bestellung, und bei acht? (6 Min.)

Spielen wir das Warten auf die Suppe in Python nach. time.sleep(0.3) heißt: „0,3 Sekunden lang nichts tun und warten“. Stell dir vor, wir hätten drei Minuten auf 0,3 Sekunden geschrumpft.

import time

def make_order(n):
    time.sleep(0.3)   # warten, bis die Suppe kocht
    return f"#{n}"

start = time.perf_counter()
done = [make_order(n) for n in range(1, 9)]
print(f"{time.perf_counter() - start:.2f}s", done)
# 2.40s ['#1', '#2', '#3', '#4', '#5', '#6', '#7', '#8']
  • time.perf_counter() ist die Uhr, mit der man Zeit misst. Liest du sie zweimal ab und ziehst die Werte voneinander ab, bekommst du die vergangenen Sekunden.
  • Acht Bestellungen zu je 0,3 Sekunden nacheinander ergeben 0,3 × 8 = 2,4 Sekunden. Von diesen 2,4 Sekunden hast du fast nichts mit den Händen getan. Es war alles Wartezeit.

Die letzten Stellen können bei jedem Lauf etwas anders ausfallen. Bei Beispielen, die Zeit messen, ist das Ergebnis immer nur „ungefähr“.

1-2. Arbeit mit Warten und Arbeit mit vollen Händen (8 Min.)

Die Arbeit in einer Küche lässt sich in zwei Sorten teilen.

Warten (I/O)Volle Hände (CPU)
In der KücheSuppe kochen, Ofen backen, auf Lieferung wartenTeig kneten, Gemüse schneiden
Im ProgrammNetzwerkantworten, Dateien lesen, DatenbankenRechnen, Komprimieren, Bildverarbeitung
WährenddessenDie Person hat nichts zu tunDie Person ist die ganze Zeit beschäftigt

Nebenläufigkeit spart vor allem dann viel Zeit, wenn es viel Warten gibt. Während eine Suppe kocht, kannst du einfach den nächsten Topf aufsetzen. Arbeit mit vollen Händen wird nur schneller, wenn wirklich mehr Leute mit anpacken, und genau dafür hat Python eine versteckte Regel. Darum geht es in Lektion 8.

1-3. Nebenläufigkeit ist nicht Parallelität (8 Min.)

Die beiden Wörter werden oft durcheinandergeworfen, bedeuten aber Verschiedenes.

  • Nebenläufigkeit (concurrency): Mehrere Aufgaben werden abwechselnd vorangebracht, sodass es von außen aussieht, als liefen sie gemeinsam. Eine Köchin setzt die Suppe auf und rührt in der Zwischenzeit in einem anderen Topf.
  • Parallelität (parallelism): Mehrere Aufgaben laufen wirklich im selben Moment. Vier Köche kneten gleichzeitig jeder seinen eigenen Teig.

Parallelität ist eine Art, Nebenläufigkeit umzusetzen. In einer Küche, in der fast nur gewartet wird, reicht schon Nebenläufigkeit mit einem einzigen Paar Hände, um deutlich schneller zu werden. Schalte in der Zeitleiste unten zwischen „Allein, eins nach dem anderen“ und „Mehrere Köche“ hin und her. Ein Balken ist eine Bestellung, die waagerechte Achse ist die Zeit.

Küchen-Zeitleiste

Bestellungen

6

Köche

3

Kochen

Warten

Abgebrochen

Fehlgeschlagen

8 Bestellungen zu je 0,3 s. Allein und nacheinander werden die Balken zu einer langen Reihe; mit mehr Köchen verteilen sie sich auf mehrere Reihen, überlappen sich und werden kürzer.
  • Bei „Allein, eins nach dem anderen“ hängen acht Balken in einer Reihe hintereinander, das dauert etwa 2,4 Sekunden.
  • Bei „Mehrere Köche“ mit 3 Köchen überlappen sich drei Reihen, etwa 0,9 Sekunden; mit 8 Köchen sind es etwa 0,3 Sekunden.
  • Dieser Versuchsaufbau ist keine Animation. Auf dem Server rufen echte Threads time.sleep auf, und gezeichnet wird, wann jede Bestellung tatsächlich begonnen und geendet hat.

1-4. Wie viel schneller wird es mit mehr Köchen? (5 Min.)

Wenn alle Bestellungen gleich lang dauern, ist die Gesamtzeit „die größte Zahl an Bestellungen, die ein Koch übernimmt, × die Zeit für eine Bestellung“.

import math

def estimate(orders, cooks, each=0.3):
    rounds = math.ceil(orders / cooks)   # höchste Zahl an Bestellungen pro Koch
    return round(rounds * each, 2)

for cooks in (1, 3, 4, 8, 16):
    print(cooks, estimate(8, cooks))
# 1 2.4
# 3 0.9
# 4 0.6
# 8 0.3
# 16 0.3
  • Bei 3 Köchen ist 8 ÷ 3 aufgerundet 3 Runden, also 0,9 Sekunden. Dieselbe Zahl wie in der Zeitleiste oben.
  • Sobald es mehr Köche als Bestellungen gibt, wird es nicht mehr schneller. Die Zeit für eine einzige Bestellung (0,3 Sekunden) ist die Untergrenze.
  • Sind die Bestellungen unterschiedlich lang, ist die längste die Untergrenze. Egal, wie du die Arbeit aufteilst: Schneller als das längste einzelne Stück geht es nicht.

1-5. Ein erster Blick auf drei Werkzeuge (8 Min.)

Python hat drei Werkzeuge, um mehrere Dinge gleichzeitig zu tun. Heute gibt es nur eine Kostprobe, ab der nächsten Lektion gehen wir sie einzeln gründlich durch.

import threading

threads = [threading.Thread(target=make_order, args=(n,)) for n in range(1, 9)]
for th in threads:
    th.start()        # acht Köche fangen gleichzeitig an
for th in threads:
    th.join()         # warten, bis alle fertig sind
# etwa 0.30 s
import asyncio

async def make_order_async(n):
    await asyncio.sleep(0.3)   # beim Warten schon die nächste Bestellung ansehen
    return f"#{n}"

async def main():
    return await asyncio.gather(*(make_order_async(n) for n in range(1, 9)))

print(asyncio.run(main()))
# ['#1', '#2', '#3', '#4', '#5', '#6', '#7', '#8']  (etwa 0.31 s)
WerkzeugIn der KüchePasst zuLektionen
threadingmehrere Köche in derselben KücheWarten, älterer Code2–7
multiprocessingeine Filialküche mit eigenem KühlschrankArbeit mit vollen Händen (CPU)8
asyncioeine Servicechefin, die allein Dutzende Tische betreutsehr viel Warten9–11

Tipp der Chefin

Klar, mit mehr Köchen geht's schneller. Dafür wird's laut in der Küche. Was passiert, wenn zwei gleichzeitig eine Zahl an dieselbe Tafel schreiben? Das siehst du in Lektion 3 mit eigenen Augen.

1-6. Nebenläufigkeit gibt es nicht umsonst (5 Min.)

Mehr Köche kosten etwas.

  • Verwaltungsaufwand: Threads anzulegen und zwischen ihnen zu wechseln kostet ebenfalls Zeit. Bei sehr kurzen Bestellungen kann es sogar langsamer werden.
  • Neue Bugs: Fassen zwei Leute gleichzeitig dieselbe Zutat an, stimmt das Ergebnis nicht mehr (Lektion 3). Wartet jeder auf das Werkzeug, das der andere hält, steht die Küche still (Lektion 5).
  • Denkaufwand: Die Annahme, dass Code Zeile für Zeile der Reihe nach läuft, gilt nicht mehr. Deshalb prüft dieser Kurs jedes Mal in der Zeitleiste mit eigenen Augen, „wann was gelaufen ist“.

Küchenschluss (10 Min.)

Das Ziel für heute Nacht war, acht Bestellungen in unter einer Sekunde rauszuschicken. Weil alle Bestellungen „Warten“ sind, reicht es, wenn acht Köche je eine übernehmen.

start = time.perf_counter()
threads = [threading.Thread(target=make_order, args=(n,)) for n in range(1, 9)]
for th in threads:
    th.start()
for th in threads:
    th.join()
print(f"{time.perf_counter() - start:.2f}s")
# 0.30s

Die Chefin stoppt ihren Timer. „Von 2,4 auf 0,3 Sekunden. Für den ersten Abend nicht schlecht. Aber wenn wir acht Köche haben, wer zählt dann, wer wie viele Gerichte gemacht hat?“

Schichtbuch — Erste Nacht. Alle 8 Bestellungen waren reines Warten; 8 Köche teilten sie sich und waren in 0,3 Sekunden fertig. Morgen werden die Köche offiziell eingestellt.

Übungen

  1. Stell in der Zeitleiste 12 Bestellungen und 4 Köche ein. Rechne zuerst aus, wie lange es dauern sollte, und lass es dann laufen.
  2. Ersetze in make_order das time.sleep(0.3) durch eine Schleife, die Zahlen addiert (Arbeit mit vollen Händen), und miss, ob es mit Threads schneller wird. Kommt dir das Ergebnis seltsam vor, erfährst du in Lektion 8 den Grund.
  3. Schreib aus deinem Alltag je drei Beispiele für „Warten“ und „Arbeit mit vollen Händen“ auf.

Rezeptkarte der Chefin

  • Warten (I/O) wird mit Nebenläufigkeit viel schneller. Arbeit mit vollen Händen (CPU) braucht echte Parallelität.

  • Nebenläufigkeit = abwechselnd vorankommen, Parallelität = im selben Moment laufen.

  • Zeit messen: start = time.perf_counter() … time.perf_counter() - start

  • Drei Werkzeuge: threading (mehrere Köche), multiprocessing (mehrere Küchen), asyncio (ein Gastraum, eine Person).

  • Nebenläufigkeit gibt es nicht umsonst: Verwaltungsaufwand und neue Bugs kommen mit.

← Zurück

Kursüberblick

Weiter →

Lektion 2 · Mehr Köche einstellen: Grundlagen von threading

Über neue Lektionen informiert werden

Wir schicken dir eine E-Mail, wenn dieser Kurs neue Lektionen bekommt oder ein Folgekurs erscheint.

Erhoben: deine E-Mail-Adresse · Zweck: Hinweise auf neue Lektionen oder den Start dieses Kurses · Speicherdauer: bis du die Löschung verlangst. Keine andere Nutzung, keine Weitergabe. Antworte einfach auf eine Benachrichtigung, dann löschen wir sie sofort.

Fragen & Antworten

Frag alles zu dieser Lektion. Fragen aus allen Sprachversionen dieser Seite erscheinen hier gemeinsam.

Wird als reiner Text angezeigt, ohne Links oder Formatierung.

R

ReflexKR

Python und Reflex zum Anfassen. Alle Beispiele wurden mit Reflex 0.10.0 ausgeführt und geprüft.

ReflexKR ist kostenlos und ohne Werbebanner. Wenn es dir geholfen hat, kannst du es mit einem Kaffee unterstützen. ☕ Spendier uns einen Kaffee

Hinweis zu Affiliate-Links
한국어English日本語简体中文EspañolDeutsch

© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0

Built with Reflex