Der Ausdruck „Race Condition“ wird verwendet, um einen Zustand zu bezeichnen, in dem mehrere Prozesse eines Systems parallel ablaufen, wobei die strikte Einhaltung einer bestimmten Reihenfolge der Schritte erwartet wird, aber aufgrund mangelnder Koordination zwischen den Einheiten nicht garantiert werden kann. Dies führt häufig zu unvorhersehbarem Verhalten und falschen Ergebnissen.
Beispiel
Zwei gleichzeitige Prozesse müssen denselben Wert inkrementieren, der nur in einer Operation (Schritt) abgerufen oder gespeichert werden kann.
Schritt | Prozess A | Gemeinsame Wert | Prozess B |
1 | Abrufen [Interner Wert: 0] | 0 | Abrufen [Internal Value: 0] |
2 | Inkrementieren [Interner Wert: 1] | 0 | Inkrementieren [Interner Wert: 1] |
3 | Speichern | 1 | Speichern |
Da keiner der beiden Prozesse wusste, dass der gemeinsame Wert an anderer Stelle manipuliert wurde, wurde nur eine der Operationen erfolgreich durchgeführt, während der Beitrag des anderen überschrieben wurde. Stell dir vor, die Prozesse A und B seien Konzertbesucher, die Tickets für ihre Lieblingsband buchen und der gemeinsame Wert steht für die Anzahl der verfügbaren Plätze. Nehmen wir an, es sei nur noch eine Karte übrig, aber beide buchen gleichzeitig, oder noch schlimmer, dasselbe passiert mit Dutzenden von Paaren.
Verbesserung
Um den Bug zu beseitigen, bietet sich ein Synchronisationsmechanismus einzubauen, wie z.B. einen Mutex Lock (siehe unteres Beispiel).
Schritt | Prozess A | Gemeinsame Wert | Prozess B |
1 | Wert gegen äußere Einflüsse sperren | 0 | |
2 | Abrufen [Interner Wert: 0] | 0 | Wert versuchen zu sperren => Fehlgeschlagen |
3 | Inkrementieren [Interner Wert: 1] | 0 | Auf Erhebung der Sperre warten... |
4 | Sperrung lösen | 1 | Auf Erhebung der Sperre warten... |
5 | 1 | Lock value | |
6 | 1 | Abrufen [Interner Wert: 1] | |
7 | 1 | Inkrementieren [Interner Wert: 2] | |
8 | 2 | Speichern | |
9 | 2 | Sperrung lösen |