Race Condition (Wettlaufsituation)
Kurz: Eine Race Condition entsteht, wenn das Ergebnis eines Programms davon abhängt, in welcher zeitlichen Reihenfolge mehrere Threads auf gemeinsame Daten zugreifen.
Genauer: Der Fehler tritt unregelmäßig auf und lässt sich schwer reproduzieren, weil die Reihenfolge von Zufälligkeiten des Schedulers abhängt. Klassisches Beispiel: zwei Threads erhöhen denselben Zähler. zaehler += 1 besteht aus Lesen, Addieren und Schreiben – wechselt der Thread dazwischen, geht eine Erhöhung verloren.
Im Detail
import threading
zaehler = 0
def zaehle():
global zaehler
for _ in range(100_000):
zaehler += 1 # nicht atomar: lesen, addieren, schreiben
threads = [threading.Thread(target=zaehle) for _ in range(4)]
for t in threads: t.start()
for t in threads: t.join()
print(zaehler) # oft weniger als 400000 (je nach Python-Version und Timing)Abhilfe
sperre = threading.Lock()
def zaehle_sicher():
global zaehler
for _ in range(100_000):
with sperre: # nur ein Thread zur Zeit im Block
zaehler += 1- Sperren (Mutex) schützen kritische Abschnitte.
- Atomare Operationen (
AtomicIntegerin Java,atomicin Go/Rust/C++) erledigen Lesen und Schreiben unteilbar. - Unveränderliche Daten (Immutability) und Nachrichtenaustausch (Queues, Kanäle, Actors) vermeiden gemeinsamen Zustand.
- Rust verhindert Datenrennen bereits zur Übersetzungszeit durch sein Besitzmodell.
Verwandt ist das Problem, dass Sperren selbst Fehler erzeugen können: Deadlock. Zum Aufspüren helfen Werkzeuge wie ThreadSanitizer und Go’s -race.
Siehe auch: Thread, Mutex, Deadlock, Nebenläufigkeit