Sitzung: Jeden Freitag in der Vorlesungszeit ab 16 Uhr c. t. im MAR 0.005. In der vorlesungsfreien Zeit unregelmäßig (Jemensch da?). Macht mit!

Informatik 4 (StuPO90)/Semaphoren: Unterschied zwischen den Versionen

(A Pattern Language for the usage of Semaphores: einführung semaphoren)
(4. "Priority": begrenzte kritische sektion -> begrenzte sektion)
 
(23 dazwischenliegende Versionen von 5 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
= TODOs =
+
= Eine "Pattern Language" für die Benutzung von  Semaphoren =
* klarer machen wie man die patterns auseinander entwickelt
 
** ich hab, dann will ich, daher mache ich...
 
 
 
= A Pattern Language for the usage of Semaphores =
 
 
::(Nach http://c2.com/cgi/wiki?PatternLanguage)
 
::(Nach http://c2.com/cgi/wiki?PatternLanguage)
  
Dafür zu sorgen, dass mehrere nebenläufige Prozesse korrekt miteinander arbeiten, ist erstaunlich schwierig. Speziell Mehrseitige Synchronisation bereitete mir beim Verstehen und Erklären besondere Probleme. Um die dabei auftretenden Probleme übersichtlicher zu erklären habe ich diese "Pattern Language" formuliert.
+
Dafür zu sorgen, dass mehrere nebenläufige Prozesse korrekt miteinander arbeiten, ist erstaunlich schwierig. Speziell Mehrseitige Synchronisation bereitete mir beim Verstehen und Erklären besondere Probleme. Um die dabei auftretenden Probleme übersichtlicher zu erklären, habe ich diese "Pattern Language" formuliert.
  
Ich würde mich sehr über Feedback (mhaecker@cs.tu-berlin.de) zu den Beispielen und Formulierungen freuen.
+
Ich würde mich sehr über Feedback (mhaecker at cs.tu-berlin.de) zu den Beispielen und Formulierungen freuen.
  
 
Folgende Probleme werden behandelt:
 
Folgende Probleme werden behandelt:
Zeile 15: Zeile 11:
 
* Locking zum gegenseitigen Ausschluss von zwei Gruppen
 
* Locking zum gegenseitigen Ausschluss von zwei Gruppen
 
* Locking für Priorisierung einer von mehreren Gruppen
 
* Locking für Priorisierung einer von mehreren Gruppen
 +
* Einseitige Synchronisation
  
Zu diesem Zweck werden hier in der Vorlesung Semaphoren eingesetzt, die eine P() (Passieren) und eine V() (Vreigeben) Operation haben. Ausserdem können Semaphoren mit einem Wert initialisiert werden der Vorgibt wie oft P() aufgerufen werden kann, bis der Aufrufer Blockiert wird.
+
Zu diesem Zweck werden hier in der Vorlesung Semaphoren eingesetzt, die eine P() (Passieren) und eine V() (Vreigeben) Operation haben. Außerdem können Semaphoren mit einem Wert initialisiert werden, der vorgibt, wie oft P() aufgerufen werden kann, bevor weitere Aufrufer blockiert werden. Für genauere Erklärungen siehe das [[Informatik 4]] Skript.
  
 
== 1. "Critical Section" ==
 
== 1. "Critical Section" ==
Eine kritische Sektion ist ein Stück Code, in dem nur ein Prozess gleichzeitig sein darf. Eine Möglichkeit das durchzusetzen, ist diese Bereiche mit Semaphoren zu schützen.
+
Eine kritische Sektion ist ein Stück Code, in dem nur ein Prozess gleichzeitig sein darf. Eine Möglichkeit das durchzusetzen ist, diese Bereiche mit Semaphoren zu schützen.
  
 
Beispiel:
 
Beispiel:
Zeile 26: Zeile 23:
  
 
criticalSection.P()
 
criticalSection.P()
.. etwas in der kritischen Sektion tun ..
+
... etwas in der kritischen Sektion tun ...
 
criticalSection.V()
 
criticalSection.V()
 
</nowiki>
 
</nowiki>
Zeile 38: Zeile 35:
  
 
restrictedSection.P()
 
restrictedSection.P()
... etwas tun in der kritischen Sektion
+
... etwas in der begrenzten Sektion tun ...
 
restrictedSection.V()
 
restrictedSection.V()
 
</nowiki>
 
</nowiki>
Zeile 45: Zeile 42:
  
 
== 3. "Mutual Exclusion" ==
 
== 3. "Mutual Exclusion" ==
Wenn ein Stück Code nur von jeweils einer Art von Prozessen betreten werden darf, dann verwendet man eine Semaphore um gegenseitigen Ausschluss zu realisieren.
+
Wenn ein Stück Code nur von jeweils einer Art von Prozessen betreten werden darf, dann verwendet man eine Semaphore, um gegenseitigen Ausschluss zu realisieren.
  
 
Beispiel:
 
Beispiel:
Zeile 52: Zeile 49:
 
hole ich mir die Semaphore
 
hole ich mir die Semaphore
  
.. etwas im kritischen Abschnitt tun ..
+
... etwas in dem kritischen Abschnitt erledigen,
 +
in dem jetzt diese Prozesse unter sich sind ...
  
 
wenn ich der letzte Prozess meiner Art bin der den kritischen Abschnitt verlässt:
 
wenn ich der letzte Prozess meiner Art bin der den kritischen Abschnitt verlässt:
gebe ich die semaphore frei
+
gebe ich die Semaphore frei
 
</nowiki>
 
</nowiki>
  
Sowohl der erste als auch der zweite Test, ob man der erste bzw. letzte ist, ist natürlich /*TODO: ist das echt so natürlich?Wenn man den Zähler dazu erwähnt schon*/ ein kritischer Abschnitt und muss entsprechend gelockt werden. Etwas formaler:
+
Den Test, ob man der erste bzw. letzte seiner Art ist, macht man üblicherweise über einen Zähler, der nach dem Inkrementieren bzw. Dekrementieren abgefragt wird. Damit wird sowohl der Eingangs- als auch der Ausgangsbereich selbst eine Critical Section und muss entsprechend behandelt werden.
  
 
  <nowiki>
 
  <nowiki>
Zeile 69: Zeile 67:
 
criticalSection.V()
 
criticalSection.V()
  
.. etwas in dem kritischen Abschnitt erledigen,
+
... etwas in dem kritischen Abschnitt erledigen,
 
in dem jetzt diese Prozesse unter sich sind ...
 
in dem jetzt diese Prozesse unter sich sind ...
  
Zeile 79: Zeile 77:
 
</nowiki>
 
</nowiki>
  
Hier wird das Muster "Critical Section" zusätzlich gebraucht, damit der Zähler zwischen seiner Veränderung und dem Test welchen Wert er hat nicht von einem anderen Prozess verändert werden kann.
+
Hier wird das Muster "Critical Section" zusätzlich gebraucht, damit der Zähler zwischen seiner Veränderung und dem Test, welchen Wert er hat, nicht von einem anderen Prozess verändert werden kann.
  
Kombiniert man "Critical Section" mit "Mutual Exclusion" dann kann man entweder die "Critical Section" direkt um den kritischen Abschnitt legen, oder sie um das gesamte außen herum "wickeln".
+
Kombiniert man "Critical Section" mit "Mutual Exclusion", dann kann man entweder die "Critical Section" direkt um den kritischen Abschnitt legen, oder sie um das Ganze außen herum "wickeln".
 +
 
 +
Alle weiteren Prozessgruppen verwenden die selbe Semaphore für den gegenseitigen Ausschluss, aber eigene Semaphoren und eigene Zähler für den kritischen Abschnitt.
  
 
== 4. "Priority" ==
 
== 4. "Priority" ==
Zwei ineinander verschachtelte Semaphoren können genutzt werden, um eine Art von Prozessen gegen andere zu priorisieren. Dies ist eine Ergänzung des vorhergehenden Musters.
+
Zwei ineinander verschachtelte Semaphoren können genutzt werden, um eine Art von Prozessen gegen andere zu priorisieren.
  
 
Beispiel:
 
Beispiel:
 
  <nowiki>
 
  <nowiki>
äusserer kritischer Abschnitt <- An dieser Semaphore bleiben alle Prozesse  
+
äußerer kritischer Abschnitt <- An dieser Semaphore bleiben alle Prozesse "hängen" bis auf einen
"hängen" bis auf einen
+
innerer kritischer Abschnitt <- an dieser Semaphore ist also immer nur maximal ein Prozess gleichzeitig
innerer Kritischer Abschnitt <- an dieser Semaphore ist also immer  
 
nur maximal ein Prozess gleichzeitig
 
  
.. kritischer Bereich ..
+
  
 
innerer Kritischer Abschnitt
 
innerer Kritischer Abschnitt
äusserer kritischer Abschnitt
+
äußerer kritischer Abschnitt
 
</nowiki>
 
</nowiki>
  
/*TODO: und die andere Prozessart?*/
+
Die Semaphore, die den inneren kritischen Abschnitt schützt, kann jetzt von einem anderen Prozess aus einer anderen Prozessgruppe gesperrt werden. Das funktioniert, da die anderen Prozesse ja gerade '''nicht''' auch an der Äußeren Semaphore warten müssen. Damit muss der priorisierte Prozess maximal so lange warten, bis der Prozess, der die innere Semaphore gerade besitzt, sie wieder freigibt. Da nur maximal ein Prozess aus der niederprioren Gruppe an der Semaphore "hängen" kann, werden alle Prozesse überholt, die an der äußeren Semaphore warten.
  
Die Semaphore, die den inneren kritischen Abschnitt schützt, kann jetzt von einem anderen Prozess aus einer anderen Prozessgruppe gelockt werden. Wenn das passiert, dann muss er maximal so lange warten, bis sie der Prozess der sie gerade besitzt freigibt, da nur einer aus dieser Gruppe daran "hängen" kann. Er hat also alle anderen Prozesse die an der äusseren Semaphore warten überholt.
+
Etwas formaler:
 
 
Etwas Formaler:
 
 
  <nowiki>
 
  <nowiki>
 
outerCriticalSection = Semaphore(1), innerCriticalSection = Semaphore(1)
 
outerCriticalSection = Semaphore(1), innerCriticalSection = Semaphore(1)
Zeile 110: Zeile 106:
 
innerCriticalSection.P()
 
innerCriticalSection.P()
 
 
.. kritischer Bereich ..
+
... kritischer Bereich ...
 
 
 
innerCriticalSection.V()
 
innerCriticalSection.V()
Zeile 116: Zeile 112:
 
</nowiki>
 
</nowiki>
  
Um dieses Muster anzuwenden muss man es mit dem Muster "Mutual Exclusion" kombinieren, indem der erste einer anderen Gruppe sich die Semaphore des inneren kritischen Abschnitts "sichert". /* TODO: klarer machen, das die andere Gruppe die innere semaphore als "mutex" verwendet. */
+
Will man "Priority" mit "Mutual Exclusion" kombinieren, dann wird der erste Block der "Mutual Exclusion" in den kritischen Bereich der "Priority" verlegt. Die priorisierten Prozesse sperren dann zusätzlich zu der Ausschluss-Semaphore noch die Semaphore des inneren kritischen Abschnitts.
 +
 
 +
Die niederprioren Prozesse:
 +
<nowiki>
 +
outerCriticalSection = Semaphore(1), innerCriticalSection = Semaphore(1),
 +
lowPriorityCounterProtection = Semaphore(1), mutex = Semaphore(1)
 +
 
 +
outerCriticalSection.P()
 +
innerCriticalSection.P()
 +
lowPriorityCounterProtection.P()
 +
lowPriorityCounter++
 +
if 1 == lowPriorityCounter
 +
mutex.P()
 +
lowPriorityCounterProtection.V()
 +
innerCriticalSection.V()
 +
outerCriticalSection.V()
 +
 
 +
... kritischer Bereich ...
 +
 
 +
lowPriorityCounterProtection.P()
 +
lowPriorityCounter--
 +
if 0 == lowPriorityCounter
 +
mutex.V()
 +
lowPriorityCounterProtection.V()
 +
</nowiki>
 +
 
 +
Die hochprioren Prozesse:
 +
<nowiki>
 +
highPriorityCounterProtection = Semaphore(1)
 +
// "mutex" und "innerCriticalSection" sind global und werden hier mitbenutzt
 +
 
 +
highPriorityCounterProtection.P()
 +
highPriorityCounter++
 +
if 1 == highPriorityCounter
 +
innerCriticalSection.P()
 +
mutex.P()
 +
highPriorityCounterProtection.V()
  
Will man "Priority" mit "Restricted Section" kombinieren, ist zu beachten, das die begrenzte kritische Sektion der Gruppe die überholt werden soll natürlich den gesamten Code mit einschließt, der die Priorität sichert. Tut man das nicht, kann das Überholen nicht garantiert werden. Auf der anderen Seite, bei den Prozessen, die überholen sollen, muss die begrenzte kritische Sektion innerhalb des Codes liegen, der die Priorität garantiert, da andernfalls in dem Spezialfall, in dem die Begrenzung auf eins liegt, das Überholen nicht funktioniert.
+
... kritischer Bereich ...
  
/* TODO: klar machen, das die beiden restrictions verschiedene semaphoren sind! */
+
highPriorityCounterProtection.P()
 +
highPriorityCounter--
 +
if 0 == highPriorityCounter
 +
mutex.V()
 +
innerCriticalSection.V()
 +
highPriorityCounterProtection.V()
 +
</nowiki>
  
/*TODO: hier einen Punkt einfügen, der einseitige Synchronisationabdeckt*/
+
Will man "Priority" mit "Restricted Section" kombinieren, ist zu beachten, dass die begrenzte Sektion der Gruppe, die überholt werden soll, natürlich den gesamten Code mit einschließt, der die Priorität sichert. Tut man das nicht, kann das Überholen nicht garantiert werden.
 +
 
 +
Auf der anderen Seite, bei den Prozessen, die überholen sollen, muss die begrenzte kritische Sektion innerhalb des Codes liegen, der die Priorität garantiert, da andernfalls in dem Spezialfall, in dem die Restriktion auf eins liegt, das Überholen nicht funktioniert. (Vorsicht: Natürlich muss bei "Restricted Section" jede Prozessgruppe eine eigene Semaphore für die Beschränkung haben.)
 +
 
 +
Der dritte wichtige Punkt ist das Holen und Freigeben der ''innerCriticalSection'' im niederprioren Prozess. Das holen muss '''vor''' dem ''mutex'' und das Freigeben '''nach''' dem ''mutex'' passieren, da das System sonst ein Deadlock produzieren kann.
  
 
== 5. "Reduction" ==
 
== 5. "Reduction" ==
 
Die Lösungen, die man aus der Kombination dieser Muster erhält, verwenden in Spezialfällen mehr Semaphoren als unbedingt nötig. Man kann daher manchmal einige der Semaphoren weglassen, da ihre Funktion schon von einer der anderen Semaphoren erfüllt werden.
 
Die Lösungen, die man aus der Kombination dieser Muster erhält, verwenden in Spezialfällen mehr Semaphoren als unbedingt nötig. Man kann daher manchmal einige der Semaphoren weglassen, da ihre Funktion schon von einer der anderen Semaphoren erfüllt werden.
 +
 +
<!-- Rausgenommen, da dies ein Beispiel mit zwei einseitigen Synchronisationen ist - wir wollen erst ein Beispiel mit einer einseitigen, und daraus dann dieses entwickeln.
 +
 +
== 6. "Einseitige Synchronisation" (Erzeuger- / Verbraucher-Probleme) ==
 +
Will man Erzeuger und Verbraucher koordinieren, so braucht man im allgemeinen Fall zwei Semaphore. Eine regelt den vorhandenen "Lagerplatz", die andere im Lager vorhandene Ressourcen.
 +
 +
Als Veranschaulichung dieses Konzeptes soll ein Lagerplatz mit einer Kapazität von n dienen. Die "LagerplatzVoll-Semaphore" dient dazu dass der Lieferant feststellen kann, dass noch Platz im Lager ist, während die "LagerplatzLeer-Semaphore" dem Konsument dazu dient festzustellen, ob noch Produkte im Lager sind.
 +
 +
Produzent:
 +
<nowiki>
 +
storageFull = Semaphore(n), storageEmpty = Semaphore(0)
 +
// Lagerplatz ist am Anfang leer
 +
 +
while true:
 +
storageFull.P()
 +
produceAGoodAndPlaceInStorage()
 +
storageEmpty.V()
 +
</nowiki>
 +
 +
Konsument:
 +
<nowiki>
 +
// storageFull und storageEmpty sind global und werden hier mitbenutzt
 +
while true:
 +
storageEmpty.P()
 +
getGoodFromStorageAndDoSomethingWithIt()
 +
storageFull.V()
 +
</nowiki>
 +
 +
Dieses Konzept ist auf alle Situationen anwendbar, die dieses Verhalten zeigen, oder bei denen Signale wie die hier gezeigten übermittelt werden müssen. Sei es nun der Kino-Wärter, der die Vorstellung beginnen soll, nachdem der Saal voll ist, oder das Flugzeug, das startet, wenn die Passagiere an Bord sind, etc.
 +
 +
Soll nur einmal ein Signal übermittelt werden, beispielsweise dass alle notwendigen Vorraussetzungen für eine einmalige Aktion jetzt erfüllt sind, dann genügt natürlich auch eine Semaphore.
 +
-->
 +
 +
[[Informatik 4|<- Zurück zur Informatik 4 Seite]]

Aktuelle Version vom 22. Mai 2007, 16:39 Uhr

Eine "Pattern Language" für die Benutzung von Semaphoren

(Nach http://c2.com/cgi/wiki?PatternLanguage)

Dafür zu sorgen, dass mehrere nebenläufige Prozesse korrekt miteinander arbeiten, ist erstaunlich schwierig. Speziell Mehrseitige Synchronisation bereitete mir beim Verstehen und Erklären besondere Probleme. Um die dabei auftretenden Probleme übersichtlicher zu erklären, habe ich diese "Pattern Language" formuliert.

Ich würde mich sehr über Feedback (mhaecker at cs.tu-berlin.de) zu den Beispielen und Formulierungen freuen.

Folgende Probleme werden behandelt:

  • Locking für kritische Sektionen
  • Locking für beschränkten Zugriff (n clients)
  • Locking zum gegenseitigen Ausschluss von zwei Gruppen
  • Locking für Priorisierung einer von mehreren Gruppen
  • Einseitige Synchronisation

Zu diesem Zweck werden hier in der Vorlesung Semaphoren eingesetzt, die eine P() (Passieren) und eine V() (Vreigeben) Operation haben. Außerdem können Semaphoren mit einem Wert initialisiert werden, der vorgibt, wie oft P() aufgerufen werden kann, bevor weitere Aufrufer blockiert werden. Für genauere Erklärungen siehe das Informatik 4 Skript.

1. "Critical Section"

Eine kritische Sektion ist ein Stück Code, in dem nur ein Prozess gleichzeitig sein darf. Eine Möglichkeit das durchzusetzen ist, diese Bereiche mit Semaphoren zu schützen.

Beispiel:

criticalSection = Semaphore(1)

criticalSection.P()
	... etwas in der kritischen Sektion tun ...
criticalSection.V()

2. "Restricted Section"

Will man einer bestimmten Anzahl von Prozessen den Aufenthalt in einem Bereich gestatten, nennt man das eine beschränkte Sektion. Dies setzt man um, indem man diese Sektion in die P()- und V()-Operationen einer Semaphore fasst, die mit dem gewünschten Wert initialisiert ist. Streng genommen ist dies also eine Erweiterung der "Critical Section".

Beispiel:

restrictedSection = Semaphore(n)

restrictedSection.P()
	... etwas in der begrenzten Sektion tun ...
restrictedSection.V()

Jetzt können maximal n Prozesse den kritischen Abschnitt gleichzeitig betreten.

3. "Mutual Exclusion"

Wenn ein Stück Code nur von jeweils einer Art von Prozessen betreten werden darf, dann verwendet man eine Semaphore, um gegenseitigen Ausschluss zu realisieren.

Beispiel:

wenn ich der erste Prozess meiner Art bin der den kritischen Abschnitt betreten will:
	hole ich mir die Semaphore

... etwas in dem kritischen Abschnitt erledigen,
	 in dem jetzt diese Prozesse unter sich sind ...

wenn ich der letzte Prozess meiner Art bin der den kritischen Abschnitt verlässt:
	gebe ich die Semaphore frei

Den Test, ob man der erste bzw. letzte seiner Art ist, macht man üblicherweise über einen Zähler, der nach dem Inkrementieren bzw. Dekrementieren abgefragt wird. Damit wird sowohl der Eingangs- als auch der Ausgangsbereich selbst eine Critical Section und muss entsprechend behandelt werden.

criticalSection = Semaphore(1), mutualExclusion = Semaphore(1)

criticalSection.P()
	howManyInCriticalSection++
	if 1 == howManyInCriticalSection:
		mutualExclusion.P()
criticalSection.V()

... etwas in dem kritischen Abschnitt erledigen,
	 in dem jetzt diese Prozesse unter sich sind ...

criticalSection.P()
	howManyInCriticalSection--
	if 0 == howManyInCriticalSection:
		mutualExclusion.V()
criticalSection.V()

Hier wird das Muster "Critical Section" zusätzlich gebraucht, damit der Zähler zwischen seiner Veränderung und dem Test, welchen Wert er hat, nicht von einem anderen Prozess verändert werden kann.

Kombiniert man "Critical Section" mit "Mutual Exclusion", dann kann man entweder die "Critical Section" direkt um den kritischen Abschnitt legen, oder sie um das Ganze außen herum "wickeln".

Alle weiteren Prozessgruppen verwenden die selbe Semaphore für den gegenseitigen Ausschluss, aber eigene Semaphoren und eigene Zähler für den kritischen Abschnitt.

4. "Priority"

Zwei ineinander verschachtelte Semaphoren können genutzt werden, um eine Art von Prozessen gegen andere zu priorisieren.

Beispiel:

äußerer kritischer Abschnitt <- An dieser Semaphore bleiben alle Prozesse "hängen" bis auf einen
	innerer kritischer Abschnitt <- an dieser Semaphore ist also immer nur maximal ein Prozess gleichzeitig

		

	innerer Kritischer Abschnitt
äußerer kritischer Abschnitt

Die Semaphore, die den inneren kritischen Abschnitt schützt, kann jetzt von einem anderen Prozess aus einer anderen Prozessgruppe gesperrt werden. Das funktioniert, da die anderen Prozesse ja gerade nicht auch an der Äußeren Semaphore warten müssen. Damit muss der priorisierte Prozess maximal so lange warten, bis der Prozess, der die innere Semaphore gerade besitzt, sie wieder freigibt. Da nur maximal ein Prozess aus der niederprioren Gruppe an der Semaphore "hängen" kann, werden alle Prozesse überholt, die an der äußeren Semaphore warten.

Etwas formaler:

outerCriticalSection = Semaphore(1), innerCriticalSection = Semaphore(1)

outerCriticalSection.P()
	innerCriticalSection.P()
		
		... kritischer Bereich ...
	
	innerCriticalSection.V()
outerCriticalSection.V()

Will man "Priority" mit "Mutual Exclusion" kombinieren, dann wird der erste Block der "Mutual Exclusion" in den kritischen Bereich der "Priority" verlegt. Die priorisierten Prozesse sperren dann zusätzlich zu der Ausschluss-Semaphore noch die Semaphore des inneren kritischen Abschnitts.

Die niederprioren Prozesse:

outerCriticalSection = Semaphore(1), innerCriticalSection = Semaphore(1), 
lowPriorityCounterProtection = Semaphore(1), mutex = Semaphore(1)

outerCriticalSection.P()
	innerCriticalSection.P()
		lowPriorityCounterProtection.P()
			lowPriorityCounter++
			if 1 == lowPriorityCounter
				mutex.P()
		lowPriorityCounterProtection.V()
	innerCriticalSection.V()
outerCriticalSection.V()

... kritischer Bereich ...

lowPriorityCounterProtection.P()
	lowPriorityCounter--
	if 0 == lowPriorityCounter
		mutex.V()
lowPriorityCounterProtection.V()

Die hochprioren Prozesse:

highPriorityCounterProtection = Semaphore(1)
// "mutex" und "innerCriticalSection" sind global und werden hier mitbenutzt

highPriorityCounterProtection.P()
	highPriorityCounter++
	if 1 == highPriorityCounter
		innerCriticalSection.P()
		mutex.P()
highPriorityCounterProtection.V()

... kritischer Bereich ...

highPriorityCounterProtection.P()
	highPriorityCounter--
	if 0 == highPriorityCounter
		mutex.V()
		innerCriticalSection.V()
highPriorityCounterProtection.V()

Will man "Priority" mit "Restricted Section" kombinieren, ist zu beachten, dass die begrenzte Sektion der Gruppe, die überholt werden soll, natürlich den gesamten Code mit einschließt, der die Priorität sichert. Tut man das nicht, kann das Überholen nicht garantiert werden.

Auf der anderen Seite, bei den Prozessen, die überholen sollen, muss die begrenzte kritische Sektion innerhalb des Codes liegen, der die Priorität garantiert, da andernfalls in dem Spezialfall, in dem die Restriktion auf eins liegt, das Überholen nicht funktioniert. (Vorsicht: Natürlich muss bei "Restricted Section" jede Prozessgruppe eine eigene Semaphore für die Beschränkung haben.)

Der dritte wichtige Punkt ist das Holen und Freigeben der innerCriticalSection im niederprioren Prozess. Das holen muss vor dem mutex und das Freigeben nach dem mutex passieren, da das System sonst ein Deadlock produzieren kann.

5. "Reduction"

Die Lösungen, die man aus der Kombination dieser Muster erhält, verwenden in Spezialfällen mehr Semaphoren als unbedingt nötig. Man kann daher manchmal einige der Semaphoren weglassen, da ihre Funktion schon von einer der anderen Semaphoren erfüllt werden.


<- Zurück zur Informatik 4 Seite