Prof. Dr. rer. nat. Roland Wism ¨uller
Aufgabenblatt 7 Musterl¨osung
Vorlesung Betriebssysteme I Wintersemester 2021/22
Aufgabe 1: Erzeuger/Verbraucher Synchronisation
a) Wenn die P-Operationen vertauscht werden, kann sich das System verklemmen: Z.B. k¨onnte der Verbraucher bei leerem Puffer zun¨achst P(mutex)ausf¨uhren und w¨urde dann anschließend inP(full)blockiert. Damutex aber noch gesperrt ist (d.h., den Wert 0 hat), w¨urden dann auch alle Erzeuger inP(mutex)blockiert, so daß sie kein Element mehr in den Puffer eintragen und auchV(full)nicht mehr aufrufen k¨onnen.
Als Daumenregel sollte man sich merken, die P-Operation f¨ur den wechselseitigen Ausschluss immer unmittelbar vor den kritischen Abschnitt zu schreiben.
b) Da V-Operationen nicht blockieren, spielt bei ihnen die Reihenfolge keine Rolle.
Aufgabe 2: Leser-Schreiber Synchronisation
Gemeinsame Variable:
Semaphore mutex = 1;
Semaphore okToWrite = 1;
Semaphore readers = 3;
int activeReaders = 0;
Schreiber:
okToWrite.P();
// write data base okToWrite.V();
Leser:
readers.P();
mutex.P();
activeReaders++;
if (activeReaders == 1) okToWrite.P();
mutex.V();
// read data base
readers.V();
mutex.P( ;
activeReaders--;
if (activeReaders == 0) okToWrite.V();
mutex.V();
Aufgabe 3: Steuerung eines Warenautomaten
Anleitung wie man solche Probleme systematisch l¨osen kann:
1) Identifizieren Sie die Prozesse des Systems
Die Prozesse sind die Aktivit¨aten, die nebenl¨aufig ausgef¨uhrt werden und sich dabei synchronisieren m¨ussen. Sie ergeben sich meist unmittelbar aus der Problemstellung.
In der Aufgabe haben wir drei Prozesse: Automat, Kunden und Lieferant.
2) Notieren Sie die Aktionen der einzelnen Prozesse
Hier muss klar werden, welcher Prozess was tut, in welcher zeitlichen Reihenfolge die Aktionen eines Prozesses ablaufen und wo es Schleifen oder Verzweigungen gibt.
Die Aktionen eines Prozesses ergeben sich meist unmittelbar aus der Aufgabenbeschreibung.
Die Synchronisationsoperationen (die P- und V-Operationen auf Semaphoren) m¨ussen Sie hier noch nicht einf¨ugen;
sie werden in Schritt 5 erg¨anzt. Die Prozesse laufen wie folgt ab:
Automat: Kunde: Lieferant:
while (true){
falls leer: warte auf Lieferant;
warte auf 5 Euro;
gib Chips-T¨ute aus;
}
warte, bis Automat frei;
wirf 5 Ein-Euro-St¨ucke ein;
warte auf Chips-T¨ute;
gib Automaten frei;
while (true){ warte zwei Tage;
f¨ulle Chips-T¨uten nach;
}
3) Identifizieren Sie die Synchronisationsbedingungen
Eine Synchronisationsbedingung ist eine zeitliche Abh¨angigkeit, die zwischen zwei oder mehr Prozessen durchge- setzt werden muss. Die Synchronisationsbedingungen ergeben sich am besten dadurch, dass man die Problembe- schreibung genau durchliest und jede zeitliche Bedingung mit einer eigenen Farbe in dem Text markiert wird.
In der Aufgabe gibt es vier Synchronisationsbedingungen:
(i) Nur einKundebenutzt den Automaten gleichzeitig (wechselseitiger Ausschluss).
(ii) EinKundewartet, bis der Automat die Ware liefert.
(iii) DerAutomatwartet, bis 5 Euro eingeworfen wurden.
(iv) Der leereAutomatwartet, bis der Lieferant 200 Chips-T¨uten gebracht hat.
4) Definieren Sie die Semaphore
Im Normalfall muss jede der Synchronisationsbedingungen mit einem eigenen Semaphor realisiert werden.
Geben Sie jeweils an, wie das Semaphor heißen soll, wie es initialisiert wird und welcher Bedingung es zugeordnet ist.
(i) mutex = 1: zum wechselseitigen Ausschluss der Kunden.
(ii) ware = 0: zur Blockierung des Kunden bis zur Waren¨ubergabe.
(iii) geld = 0: zur Blockierung des Automaten bis zur Geld¨ubergabe.
(iv) chips = 200: zur Blockierung des Automaten, falls er leer ist.
5) Erg¨anzen Sie die Prozesse aus Schritt 2 durch die Semaphor-Operationen
Jetzt m¨ussen Sie die P- und V-Operationen der Semaphore, die in Schritt 4 eingef¨uhrt wurden, in die Prozesse aus Schritt 2 einf¨ugen. P-Operationen m¨ussen dabei an die Stellen gesetzt werden, an denen ein Prozess auf ein bestimmtes Ereignis warten muss (also ggf. blockiert werden soll). V-Operationen kommen an die Stellen, an denen ein Prozess einem anderen signalisiert, dass er jetzt weiterlaufen darf.
Eine erste L¨osung sieht daher wie folgt aus:
Semaphore mutex = 1;
Semaphore ware = 0;
Semaphore geld = 0;
Semaphore chips = 200;
int count=200;
Automat: Kunde: Lieferant:
while (true){
// falls leer: warte auf Lieferant;
P(chips);
// warte auf 5 Euro;
for (int i=0; i<5; i++) P(geld);
//gib Chips-T¨ute aus;
count–;
V(ware);
}
// warte, bis Automat frei;
P(mutex);
// wirf 5 Ein-Euro-St¨ucke ein;
for (int i=0; i<5; i++) V(geld);
// warte auf Chips-T¨ute;
P(ware);
// gib Automaten frei;
V(mutex);
while (true){ warte zwei Tage;
//f¨ulle Chips-T¨uten nach;
for (int i=count; i<200; i++) V(chips);
count = 200;
}
Da wir in der Vorlesung davon ausgehen, daß der Z¨ahlerwert eines Semaphors nicht ausgelesen werden kann1, brauchen wir einen zus¨atzlichen Z¨ahlercount, der die Chipst¨uten im Automaten mitz¨ahlt.
Achtung:Die obige L¨osung hat noch eine m¨oglicheRace-Conditionbeim Zugriff aufcount! Um dieses Problem zu l¨osen, m¨ussen wir f¨ur einen wechselseitigen Ausschluss zwischen Automat und Lieferant sorgen, der sicher- stellt, daßcountimmer identisch mit dem Z¨ahler des Semaphorschipsist. Dazu verwenden wir ein Semaphore mutex2, das mit 1 initialisiert wird.
Semaphore mutex = 1;
Semaphore mutex2 = 1;
Semaphore ware = 0;
Semaphore geld = 0;
Semaphore chips = 200;
int count=200;
Automat: Kunde: Lieferant:
while (true){ P(mutex2);
// falls leer: warte auf Lieferant;
P(chips);
// warte auf 5 Euro;
for (int i=0; i<5; i++) P(geld);
//gib Chips-T¨ute aus;
count–;
V(ware);
V(mutex2);
}
// warte, bis Automat frei;
P(mutex);
// wirf 5 Ein-Euro-St¨ucke ein;
for (int i=0; i<5; i++) V(geld);
// warte auf Chips-T¨ute;
P(ware);
// gib Automaten frei;
V(mutex);
while (true){ warte zwei Tage;
//f¨ulle Chips-T¨uten nach;
P(mutex2);
for (int i=count; i<200; i++) V(chips);
count = 200;
V(mutex2);
}
Anmerkungen:
• In der Klausur m¨ussen Sie nur die Ergebnisse der Schritte 4 und 5 hinschreiben, es sei denn, es wird ausdr¨uck- lich anders verlangt.
• In der Klausur werden derart komplexe Synchronisationsaufgaben nicht verlangt.
Aufgabe 4: Synchronisation mit Semaphoren
a) Falsch. DaTnur hochgez¨ahlt wird, wennSvorher heruntergez¨ahlt wurde (und umgekehrt), gilt immer, daßS+T≤2 ist. Somit k¨onnen h¨ochstens zwei der drei Threads die Prozedurprint()zur selben Zeit ausf¨uhren.
b) Falsch. Da zu BeginnS>0, kann ThreadBauch als erstes einBausgeben.
1Reale Implementierungen lassen dies ggf. zu.
c) Richtig. Da zu BeginnT= 0, wird ThreadCblockiert, bis einAoder einBausgegeben wurde.
d) Falsch. Nach der AusgabeABist SemaphorS= 0, somit kann nur noch einCausgegeben werden.
e) Richtig. Nach der AusgabeABist SemaphorT= 2, somit kann zweimal einCausgegeben werden.
f) Falsch. Nach einer AusgabeCCist Semaphor Tauf jeden Fall 0, somit kann kein weiteresCmehr ausgegeben werden.
g) Falsch. Eine Verklemmung ist hier nicht m¨oglich, da jeder Thread nur eine einzigeP-Operation ausf¨uhrt, also nie blockiert, w¨ahrend er ein anderen Semaphor h¨alt.
Aufgabe 5: Synchronisation mit Semaphoren
// Semaphore und globale Variable
// Thread A // Thread B // Thread C
Semaphore fertig = ...;
erstelleCodeGeruest();
programmiere();
...
...
programmiere();
programmiere();
...
...
...
...
testeProgramm();
...
Semaphore start = ...;0 0
P(start); P(start);
V(start); V(start);
V(fertig);
V(fertig);
P(fertig); P(fertig);
Aufgabe 6: Leser-Schreiber Synchronisation
monitor ReaderWriter boolean writerIsActive;
integer activeReaders;
condition okToAccess;
(* Initialisierung *) writerIsActive := false;
activeReaders := 0;
procedure ReadBegin begin
while writerIsActive do wait(okToAccess);
activeReaders := activeReaders + 1;
end;
procedure ReadEnd begin
activeReaders := activeReaders - 1;
if activeReaders = 0 then signal(okToAccess);
end;
procedure WriteBegin begin
while writerIsActive or activeReaders > 0 do wait(okToAccess);
writerIsActive := true;
end;
procedure WriteEnd
begin
writerIsActive := false;
signal(okToAccess);
end;
end monitor;