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
Zeit 0:00–0:50
Der Bon für heute Nacht
#01 · Erste Nacht
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.“
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.Die letzten Stellen können bei jedem Lauf etwas anders ausfallen. Bei Beispielen, die Zeit messen, ist das Ergebnis immer nur „ungefähr“.
Die Arbeit in einer Küche lässt sich in zwei Sorten teilen.
| Warten (I/O) | Volle Hände (CPU) | |
|---|---|---|
| In der Küche | Suppe kochen, Ofen backen, auf Lieferung warten | Teig kneten, Gemüse schneiden |
| Im Programm | Netzwerkantworten, Dateien lesen, Datenbanken | Rechnen, Komprimieren, Bildverarbeitung |
| Währenddessen | Die Person hat nichts zu tun | Die 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.
Die beiden Wörter werden oft durcheinandergeworfen, bedeuten aber Verschiedenes.
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
time.sleep auf, und gezeichnet wird, wann jede Bestellung tatsächlich begonnen und geendet hat.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.3Python 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 simport 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)| Werkzeug | In der Küche | Passt zu | Lektionen |
|---|---|---|---|
threading | mehrere Köche in derselben Küche | Warten, älterer Code | 2–7 |
multiprocessing | eine Filialküche mit eigenem Kühlschrank | Arbeit mit vollen Händen (CPU) | 8 |
asyncio | eine Servicechefin, die allein Dutzende Tische betreut | sehr viel Warten | 9–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.
Mehr Köche kosten etwas.
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.30sDie 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.
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.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.
Über neue Lektionen informiert werden
Wir schicken dir eine E-Mail, wenn dieser Kurs neue Lektionen bekommt oder ein Folgekurs erscheint.
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© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0
Fragen & Antworten
Frag alles zu dieser Lektion. Fragen aus allen Sprachversionen dieser Seite erscheinen hier gemeinsam.