Ein kritischer Abschnitt (englisch critical section) ist der Codebereich, in dem eine nebenläufige Anwendung auf geteilte Daten zugreift — eine Zählervariable, eine Warteschlange, ein Dateideskriptor. Läuft dieser Bereich in mehreren Threads gleichzeitig, entsteht eine Race Condition. Deshalb darf sich der kritische Abschnitt nie mit einem anderen überlappen.
Die drei klassischen Anforderungen
Die Betriebssystem-Theorie (Klassiker von Dijkstra bis Silberschatz) verlangt von einer Lösung des Kritische-Abschnitt-Problems:
- Gegenseitiger Ausschluss (Mutual Exclusion): Nie führen zwei Prozesse ihren kritischen Abschnitt gleichzeitig aus.
- Fortschritt (Progress): Ist der Bereich frei und interessiert sich ein Prozess, muss er eintreten können — keiner darf außen vor gehalten werden.
- Begrenztes Warten (Bounded Waiting): Es gibt eine Obergrenze, wie oft andere Prozesse vor einem selbst eintreten dürfen — Fairness.
Lösungen: vom Peterson-Algorithmus zur Hardware
Der Peterson-Algorithmus (Gary L. Peterson, 1981) löst das Problem für zwei Prozesse rein in Software: Jeder Prozess setzt sein Flag, der zuletzt gesetzte weist dem anderen den Vortritt. Er beweist alle drei Anforderungen und ist bis heute das Standardbeispiel in Lehrbüchern. Praktisch verlassen sich moderne Systeme auf Hardware-Unterstützung: Test-and-Set, Compare-and-Swap (CAS) oder Load-Linked/Store-Conditional. Darauf bauen die eigentlichen Werkzeuge auf — der Mutex als Sperre mit Eigentümer und der Semaphor als Zählmechanismus für Ressourcenpools.
Das klassische Beispiel: i = i + 1
Eine einzige Inkrement-Anweisung ist nicht atomar: Lesen, Addieren und Zurückschreiben sind drei Schritte. Unterbrechen sich zwei Threads genau dazwischen, geht ein Inkrement verloren. Solche Stellen — man nennt sie read-modify-write-Zyklen — sind die typischen Kandidaten für einen kritischen Abschnitt. Für einzelne Variablen sind atomare Operationen (fetch-and-add, CAS-Schleifen) oft die schnellere Lösung; für längere Abläufe braucht es eine Sperre.
Regeln für die Praxis
- Kritische Abschnitte so kurz wie möglich halten — alles andere außerhalb legen.
- Sperr-Guards (RAII) verwenden, damit die Sperre auch bei Ausnahmen freigegeben wird.
- Verschachtelte kritische Abschnitte vermeiden oder in fester Reihenfolge betreten, sonst droht ein Deadlock.
- Besteht zwischen zwei Threads ein Daten-Wettlauf, ist die betroffene Stelle ein kritischer Abschnitt — und die Lösung gehört dorthin, nicht in großflächige Sperren um den ganzen Ablauf.
Kritische Abschnitte sind der Kern jeder Synchronisation: Sie machen aus dem strukturellen Nebeneinander der Nebenläufigkeit ein kontrolliertes, vorhersagbares Miteinander.