Wettlaufsituation

Eine Wettlaufsituation[1], aus dem Englischen auch Race Condition (deutsch Wettlauf-Bedingung) oder Race Hazard (deutsch Wettlauf-Risiko), mitunter auch „kritische Wettlaufsituation“, bezeichnet in der Programmierung eine Konstellation, in der das Ergebnis einer Operation vom zeitlichen Verhalten bestimmter Einzeloperationen oder der Umgebung abhängt. Der Begriff stammt von der Vorstellung, dass zwei Signale wettlaufen, um die Ausgabe als erstes zu beeinflussen. Im Allgemeinen ist die Möglichkeit zu vermeiden, dass eine Race Condition entsteht.

Unbeabsichtigte Wettlaufsituationen sind ein häufiger Grund für schwer auffindbare, nichtdeterministische Programmfehler. Bezeichnend für solche Situationen ist, dass bereits die veränderten Bedingungen zum Programmtest, wie zusätzliches Logging oder Debug-Modus, zu einem völligen Verschwinden der Symptome führen können, siehe hierzu auch Heisenbug. Zur Vermeidung solcher Konstellationen können bei der Programmerstellung beispielsweise Semaphore eingesetzt werden.

Beispiel

Zwei gleichzeitig laufende Systeme wollen denselben Wert erhöhen. Die notwendigen Einzelschritte, die jedes der beiden Systeme durchlaufen muss, sind:

  1. Wert lesen: Der Wert wird aus dem externen Speicher in den internen Speicher gelesen.
  2. Wert erhöhen: Der Wert wird im internen Speicher um 1 erhöht.
  3. Wert schreiben: Der Wert wird aus dem internen Speicher zurück in den externen Speicher geschrieben.

Angenommen, der Wert betrage anfangs 1. Das erste System heißt A, das zweite System B. Erhöhen beide Systeme den Wert, ist der erwartete neue Wert 3. Wenn System A zeitlich vor System B arbeitet, wird das auch so sein:

ZeitpunktSystem AGespeicherter WertSystem B
1Einlesen des Wertes
Wert: 1
1
2Erhöhen des internen Wertes um eins
Wert: 2
1
3Speichern des Wertes2
42Einlesen des Wertes
Wert: 2
52Erhöhen des internen Wertes um eins
Wert: 3
63Speichern des Wertes

Arbeiten beide Systeme gleichzeitig und ist die Reihenfolge der Befehle unbestimmt, kann die Wettlaufsituation jedoch dazu führen, dass der tatsächlich erhaltene, neue Wert stattdessen 2 beträgt:

ZeitpunktSystem AGespeicherter WertSystem B
1Einlesen des Wertes
Wert: 1
1Einlesen des Wertes
Wert: 1
2Erhöhen des internen Wertes um eins
Wert: 2
1Erhöhen des internen Wertes um eins
Wert: 2
3Speichern des Wertes2Speichern des Wertes

Zur Vermeidung des Problems müsste A den Zugriff auf den Wert bis zum Abschluss der Veränderung so sperren, dass B warten muss, bis A seinen Zugriff auf den Wert beendet hat.

ZeitpunktSystem AGespeicherter WertSystem B
1Sperrung gegen fremde Zugriffe
(falls dies nicht möglich ist: warten)
1
2Einlesen des Wertes
Wert: 1
1Versuch: Sperrung gegen fremde Zugriffe
(da nicht möglich: warten)
3Erhöhen des internen Wertes um eins
Wert: 2
1Auf Freigabe warten...
4Speichern des Wertes2Auf Freigabe warten...
5Aufheben der Sperrung2Sperrung gegen fremde Zugriffe
(nun erfolgreich)
62Einlesen des Wertes
Wert: 2
72Erhöhen des internen Wertes um eins
Wert: 3
83Speichern des Wertes
93Aufheben der Sperrung

Siehe auch

Einzelnachweise

  1. Simon Hoffmann, Rainer Lienhart: OpenMP. Eine Einführung in die parallele Programmierung mit C/C++. Online-Ausgabe des korrigierten Nachdrucks. Springer-Verlag, Berlin und Heidelberg 2009, S. 92 (Download über SpringerLink).