38
2 Spezifikation und Modellierung
sein. Dieser gegenseitige Ausschluss ist notwendig, um die unerwünschte Vermischung der Ausführung verschiedener Methoden in einer Umgebung mit
mehreren Threads zu verhindern. Warum ist dieser Code nun problematisch?
Der Grund dafür ist, dass vaaueChanged versuchen könnte, exklusiven Zugriff auf eine bestimmte Ressource (z.B. R) zu erhalten. Wenn diese Ressource
bereits von einer anderen Methode (z.B. A) belegt ist, wird dieser Zugriff verzögert, bis A die Ressource R freigibt. Wenn nun A die Methode addListener
oder setVaaue (möglicherweise indirekt) aufruft, bevor R freigegeben wurde,
entsteht eine Verklemmung zwischen diesen Methoden: setVaaue wartet auf
R, die Freigabe von R erfordert, dass A fortfahren kann, A kann aber nicht
fortfahren, bevor sein Aufruf der Methode setVaaue oder setListener zurückkehrt. Dadurch entsteht die Verklemmung.
Dieses Beispiel verdeutlicht, dass Verklemmungen als Folge der Verwendung
mehrerer Threads entstehen können, wenn diese beliebig verdrängt werden
können und damit gegenseitigen Ausschluss für den Zugriff auf kritische
Ressourcen benötigen. Lee hat gezeigt [330], dass viele der vorgeschlagenen „Lösungen” des Problems selbst wieder problematisch sind. Also ist auch
dieses sehr einfache Verhalten in einer von-Neumann-Umgebung mit mehreren
Threads nur schwer korrekt zu implementieren. Offenbar können Menschen
Nebenläufigkeit nur sehr schlecht verstehen und es besteht das Risiko, dass
mögliche Verklemmungen übersehen werden, auch wenn der Code gründlichst
inspiziert wurde.
∇
Lee kam daher zu der drastischen Schlussfolgerung, dass „nichttriviale, mit
Threads, Semaphoren und Mutexen entwickelte Software für Menschen unverständlich ist” und dass „Threads als ein Modell für Nebenläufigkeit nur
sehr schlecht zu eingebetteten Systemen passen. ... sie funktionieren nur gut
... wenn best-effort Scheduling-Verfahren ausreichend sind” [333].
Die Gründe der Entstehung von Verklemmungen wurden detailliert im Zusammenhang mit Betriebssystemen untersucht (z.B. in [507]). Es gibt hier
vier wohlbekannte Bedingungen, die erfüllt sein müssen, damit eine Verklemmung eintreten kann: gegenseitiger Ausschluss, kein Entzug von Ressourcen,
das Halten von Ressourcen, während auf eine weitere Ressource gewartet
wird und schließlich die gegenseitige Abhängigkeit von Threads. Das erwähnte Beispiel erfüllt alle vier Kriterien. Die Betriebssystemtheorie stellt keine
allgemeingültige Lösung für dieses Problem bereit. Seltene Verklemmungen
mögen bei einem PC annehmbar sein, in sicherheitskritischen Systemen sind
sie aber keinesfalls akzeptabel.
Wir möchten nun Systeme so spezifizieren, dass wir uns keine Sorgen um mögliche Verklemmungen machen müssen. Daher erscheint es sinnvoll, Berechnungsmodelle zu betrachten, die nicht auf von-Neumann-Prinzipien basieren und damit
das Problem von Verklemmungen umgehen. Wir beginnen die Betrachtung solcher Berechnungsmodelle im folgenden Abschnitt. Darin zeigen wir, dass das
Observer-Muster mit anderen Berechnungsmodellen einfacher korrekt implementierbar ist.
2 Spezifikation und Modellierung
sein. Dieser gegenseitige Ausschluss ist notwendig, um die unerwünschte Vermischung der Ausführung verschiedener Methoden in einer Umgebung mit
mehreren Threads zu verhindern. Warum ist dieser Code nun problematisch?
Der Grund dafür ist, dass vaaueChanged versuchen könnte, exklusiven Zugriff auf eine bestimmte Ressource (z.B. R) zu erhalten. Wenn diese Ressource
bereits von einer anderen Methode (z.B. A) belegt ist, wird dieser Zugriff verzögert, bis A die Ressource R freigibt. Wenn nun A die Methode addListener
oder setVaaue (möglicherweise indirekt) aufruft, bevor R freigegeben wurde,
entsteht eine Verklemmung zwischen diesen Methoden: setVaaue wartet auf
R, die Freigabe von R erfordert, dass A fortfahren kann, A kann aber nicht
fortfahren, bevor sein Aufruf der Methode setVaaue oder setListener zurückkehrt. Dadurch entsteht die Verklemmung.
Dieses Beispiel verdeutlicht, dass Verklemmungen als Folge der Verwendung
mehrerer Threads entstehen können, wenn diese beliebig verdrängt werden
können und damit gegenseitigen Ausschluss für den Zugriff auf kritische
Ressourcen benötigen. Lee hat gezeigt [330], dass viele der vorgeschlagenen „Lösungen” des Problems selbst wieder problematisch sind. Also ist auch
dieses sehr einfache Verhalten in einer von-Neumann-Umgebung mit mehreren
Threads nur schwer korrekt zu implementieren. Offenbar können Menschen
Nebenläufigkeit nur sehr schlecht verstehen und es besteht das Risiko, dass
mögliche Verklemmungen übersehen werden, auch wenn der Code gründlichst
inspiziert wurde.
∇
Lee kam daher zu der drastischen Schlussfolgerung, dass „nichttriviale, mit
Threads, Semaphoren und Mutexen entwickelte Software für Menschen unverständlich ist” und dass „Threads als ein Modell für Nebenläufigkeit nur
sehr schlecht zu eingebetteten Systemen passen. ... sie funktionieren nur gut
... wenn best-effort Scheduling-Verfahren ausreichend sind” [333].
Die Gründe der Entstehung von Verklemmungen wurden detailliert im Zusammenhang mit Betriebssystemen untersucht (z.B. in [507]). Es gibt hier
vier wohlbekannte Bedingungen, die erfüllt sein müssen, damit eine Verklemmung eintreten kann: gegenseitiger Ausschluss, kein Entzug von Ressourcen,
das Halten von Ressourcen, während auf eine weitere Ressource gewartet
wird und schließlich die gegenseitige Abhängigkeit von Threads. Das erwähnte Beispiel erfüllt alle vier Kriterien. Die Betriebssystemtheorie stellt keine
allgemeingültige Lösung für dieses Problem bereit. Seltene Verklemmungen
mögen bei einem PC annehmbar sein, in sicherheitskritischen Systemen sind
sie aber keinesfalls akzeptabel.
Wir möchten nun Systeme so spezifizieren, dass wir uns keine Sorgen um mögliche Verklemmungen machen müssen. Daher erscheint es sinnvoll, Berechnungsmodelle zu betrachten, die nicht auf von-Neumann-Prinzipien basieren und damit
das Problem von Verklemmungen umgehen. Wir beginnen die Betrachtung solcher Berechnungsmodelle im folgenden Abschnitt. Darin zeigen wir, dass das
Observer-Muster mit anderen Berechnungsmodellen einfacher korrekt implementierbar ist.
