Dies hängt davon ab, wie Sperren implementiert werden. Wenn Sie es wie im Wikipedia-Artikel tun, dh den kritischen Abschnitt mit einem Booleschen Wert pro Prozess¹ schützen, sind Sie mit Sicherheit in Schwierigkeiten. Wenn ein Prozess stirbt, wird sein Flag niemals zurückgesetzt, sodass der andere Prozess für immer wiederholt wird.
In der Praxis können Sie Ihren Code vor vielen Arten des Sterbens schützen. Nehmen Sie zum Beispiel diese Implementierung im Java-Stil:
flag[1] = true;
turn = 1;
while ( flag[0] == true && turn == 1 ) { Thread.yield(); }
try {
// critical section
}
finally {
flag[1] = false;
}
Dadurch wird sichergestellt, dass das Flag zurückgesetzt wird, was auch immer im kritischen Abschnitt passiert, solange das System den Fehler behandelt. In Java gilt dies auch für Stapel- und Heap-Überläufe. Wenn der Prozess nicht buchstäblich verschwindet ( kill
², Prozessorausfall, Netzwerkunterbrechung, ...), sind Sie sicher. Beachten Sie, dass die meisten unkritischen Programme in diesen Fällen fehlschlagen. Wie kann sie mit einem Fehler umgehen, den sie nicht ausführen? - Das muss also in vielen Fällen akzeptiert werden. Bei Bedarf können Sie beim Neustart mit Inkonsistenzen umgehen.
Wenn Sie geeignete Sperren auf Sprachebene verwenden, kann das Laufzeitsystem verschwindende Sperrenbesitzer verarbeiten, dh Sperren mit toten Besitzern freigeben. Sie können dies selbst simulieren, indem Sie jedem Prozess einen Totmannschalter geben, den die anderen lesen können, oder direkt prüfen, ob der Prozess des Schlossbesitzes noch aktiv ist (sofern das System dies unterstützt).
- Das lässt sich sowieso nicht gut skalieren.
- In Java sollte meiner Meinung
finalize
nach auch auf ausgeführt werden kill
, aber dies wird durch die Spezifikation nicht garantiert. kill -9
ist wahrscheinlich ein Todesurteil für jede Lösung, bei der der Sterbevorgang etwas unternehmen muss.