Systemsoftware
Systemsoftware
Systemsoftware
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
<strong>Systemsoftware</strong><br />
Jürgen Nehmer, WS 2002/03<br />
Thread-Synchronisation<br />
3. Monitore<br />
<strong>Systemsoftware</strong> - Lektion X 1<br />
Monitor-Definition (Hoare 1974)<br />
• Ein Monitor ist eine Datenstruktur<br />
mit darauf definierten Operationen,<br />
die sich wechselseitig ausschließen<br />
– Datenstruktur = shared region<br />
– Benutzung der Datenstruktur nur<br />
über definierte Operationen<br />
– Einbettung in höhere Programmiersprachen<br />
essentiell<br />
Thread<br />
Adressraum<br />
Thread<br />
• Vorteil:<br />
– Daten und Zugriffsfunktionen sind<br />
an einem Ort konzentriert<br />
– bessere Änderbarkeit<br />
Monitor<br />
Operationen des Monitors<br />
gekapselte Daten im Monitor<br />
<strong>Systemsoftware</strong> - Lektion X 2
Das Sprachkonzept (Concurrent Pascal, CHILL, Java)<br />
MONITOR Monitorname (Parameter)<br />
Datendeklarationen; /*von außen unsichtbar*/<br />
ENTRY Funktionsname1 (Parameter) {Prozedur}<br />
ENTRY Funktionsname2 (Parameter) {Prozedur}<br />
.............<br />
ENTRY FunktionsnameN (Parameter) {Prozedur}<br />
INIT {Initialisierung}<br />
END Monitorname<br />
/* Monitorinitialisierung */<br />
Monitorname (aktuelle Parameter);<br />
/* Aufruf einer Monitorprozedur */<br />
Monitorname.Funktionsname(aktuelle Parameter);<br />
<strong>Systemsoftware</strong> - Lektion X 3<br />
Condition-Variable: ein Hilfsmittel zur einfachen<br />
Formulierung bedingter kritischer Abschnitte<br />
CONDITION a,b,c; /* Condition-Variable sind Warte- */<br />
/* schlangen, in denen Threads auf den Eintritt */<br />
/* einer bestimmten Bedingung warten */<br />
/* Warten auf den Eintritt einer Bedingung */<br />
Conditionvariable.Wait([Priorität]);<br />
/* Signalisieren des Eintritts einer Bedingung */<br />
Conditionvariable.Signal([Priorität]);<br />
/* liefert die Anzahl wartender Threads zurück */<br />
int Conditionvariable.Status();<br />
• Anmerkung: Condition-Variable sind nur innerhalb von Monitoren definiert<br />
<strong>Systemsoftware</strong> - Lektion X 4
Veranschaulichung von Signal und Wait<br />
Monitor M<br />
Monitorproz.<br />
CV1<br />
CV1.Wait;<br />
Neuzutritt über Monitorprozeduraufruf<br />
CV1.Signal<br />
Wiedereintritt nach Wait<br />
CV2.Wait;<br />
CV2<br />
CV2.Signal<br />
<strong>Systemsoftware</strong> - Lektion X 5<br />
Semantik von Wait()<br />
P r der im Monitor M rechnende Thread, der die Wait-Operation aufruft<br />
B eine Bedingung über den Monitordaten<br />
P die Menge aller zum Monitor M Zutritt suchenden Threads<br />
CV eine auf die Erfüllung von B wartende Threadmenge<br />
(1) {¬B∧(P'=∅)∧(M'=BELEGT)} CV.Wait ( )<br />
{¬B∧(P r =Blocked)∧(CV={P r }∪CV')∧(P=∅)∧(M=FREI)<br />
(2) {¬B∧(P'≠∅)∧(M'=BELEGT)} CV.Wait ( )<br />
{¬B∧(P r =Blocked)∧(CV={P r }∪CV')∧(P=P'-{P x },P x ∈P')<br />
∧(P x =Ready)∧(M=BELEGT)<br />
<strong>Systemsoftware</strong> - Lektion X 6
Semantik von Signal()<br />
(1) {B∧(CV'=∅)} CV.Signal ( ) {B∧(CV=∅)}<br />
• Variante I: kein Besitzwechsel, Befreiung höchstens eines Threads aus CV<br />
(2) {B∧(CV'≠∅)} CV.Signal ( ) {B∧(CV=CV'-{P x },P x ∈CV')∧(P=P'∪{P x })}<br />
• Variante II: kein Besitzwechsel, Befreiung aller Threads aus CV<br />
(2') {B∧(CV'≠∅)} CV.Signal ( ) {B∧(CV=∅)∧(P=P'∪CV')}<br />
• Variante III: Besitzwechsel vom signalisierenden auf einen signalisierten<br />
Thread (Hoare 1974)<br />
(2'') {B∧(CV'≠∅)} CV.Signal ( ) {B∧(P=P'∪{P r }∧(P r =Blocked) ∧(CV=CV'- {P x },<br />
P x ∈CV')∧(P x =Ready)}<br />
<strong>Systemsoftware</strong> - Lektion X 7<br />
Programmierregeln<br />
• Signal-Varianten I und II<br />
– keine Garantie, dass die Bedingung B nach Wait erfüllt ist, deshalb<br />
Benutzung von Wait immer in der while-Schleife:<br />
while (!B) Conditionvariable.Wait();<br />
• Signal-Variante III:<br />
– war B unmittelbar vor Signal erfüllt, dann ist B auch garantiert nach Wait<br />
erfüllt, deshalb ist die Benutzung von Wait auch in if-Anweisung sicher:<br />
if (!B) Conditionvariable.Wait();<br />
<strong>Systemsoftware</strong> - Lektion X 8
Beispiel 1: Monitor = exklusive Ressource<br />
MONITOR Disc<br />
ENTRY Read (PlattenAdr, SpeicherAdr, Länge)<br />
{Lesevorgang durchführen}<br />
ENTRY Write (SpeicherAdr, PlattenAdr, Länge)<br />
{Schreibvorgang}<br />
INIT {Platte in Betriebsbereitschaft versetzen}<br />
END Disc<br />
• Prozesse benutzen den Monitor in der Form:<br />
Disc.Read(Von,Nach,Länge);<br />
Disc.Write(Von,Nach,Länge);<br />
<strong>Systemsoftware</strong> - Lektion X 9<br />
Beispiel 2: Kritische Abschnitte mit Monitoren<br />
• Benutzungsmuster der<br />
Ressource Disc:<br />
Aquire();<br />
Use();<br />
Use();<br />
Use();<br />
....<br />
Use();<br />
Release();<br />
• Es macht keinen Sinn, die Use-<br />
Operationen in den Monitor zu legen<br />
MONITOR Disc<br />
int busy; /*0=frei,1=belegt*/<br />
Condition nonbusy;<br />
ENTRY Acquire() {<br />
if (busy==1) nonbusy.Wait();<br />
busy++;<br />
}<br />
ENTRY Release() {<br />
busy--;<br />
nonbusy.Signal();<br />
}<br />
INIT {busy=0}<br />
END Disc<br />
• Benutzung in der Form<br />
Disc.Acquire();..Disc.Release();<br />
<strong>Systemsoftware</strong> - Lektion X 10
Beispiel 3: Verwaltung eines Ressourcen-Pools<br />
MONITOR DiscPool (int Zahl)<br />
enum<br />
{frei,belegt} DiscStatus[N];<br />
int busy; /*Zahl Laufwerke*/<br />
Condition nonbusy;<br />
ENTRY int GetDisc() {<br />
int i;<br />
i=1;<br />
if (busy==N)<br />
nonbusy.Wait();<br />
while (DiscStatus[i]==belegt)<br />
i++;<br />
DiscStatus[i]=belegt;<br />
busy++;<br />
return i;<br />
}<br />
ENTRY PutDisc(int UsedDisc) {<br />
DiscStatus[UsedDisc]=frei;<br />
busy--;<br />
nonbusy.Signal();<br />
}<br />
INIT {<br />
N=...; /*Anzahl Laufwerke*/<br />
DiscStatus[0]=frei;<br />
DiscStatus[1]=frei;<br />
.....<br />
DiscStatus[N-1]=frei;<br />
busy=0;<br />
}<br />
END DiscPool<br />
<strong>Systemsoftware</strong> - Lektion X 11<br />
Beispiel 4: Reader-Writer-Problem (Reader-Bevorzugung)<br />
MONITOR ReadWrite<br />
int ReadCount, Writeflag;<br />
Condition OKtoRead,OKtoWrite;<br />
ENTRY StartRead() {<br />
Readcount++;<br />
if (Writeflag==1)<br />
OKtoRead.Wait();<br />
OKtoRead.Signal();<br />
}<br />
ENTRY EndRead() {<br />
Readcount--;<br />
if (Readcount==0)<br />
OKtoWrite.Signal();<br />
}<br />
ENTRY StartWrite() {<br />
if ((Readcount>0)¦¦<br />
(Writeflag==1))<br />
OKtoWrite.Wait();<br />
Writeflag=1;<br />
}<br />
ENTRY EndWrite() {<br />
Writeflag=0;<br />
if (OKtoRead.Status()>0)<br />
OKtoRead.Signal();<br />
else OKtoWrite.Signal();<br />
}<br />
INIT {<br />
Readcount=0;<br />
Writeflag=0;<br />
}<br />
END ReadWrite<br />
<strong>Systemsoftware</strong> - Lektion X 12
Beispiel 5:Reader-Writer-Problem (Writer-Bevorzugung)<br />
MONITOR ReadWrite<br />
int Readcount, Writecount,<br />
Writeflag;<br />
Condition OKtoRead, OKtoWrite;<br />
ENTRY StartRead() {<br />
if (Writecount>0)<br />
OKtoRead.Wait();<br />
Readcount++;<br />
OKtoRead.Signal();<br />
}<br />
ENTRY EndRead() {<br />
Readcount--;<br />
if (Readcount==0)<br />
OKtoWrite.Signal();<br />
}<br />
ENTRY StartWrite() {<br />
Writecount++;<br />
if ((Readcount>0)¦¦<br />
(Writeflag=1))<br />
OKtoWrite.Wait();<br />
Writeflag=1;<br />
}<br />
ENTRY EndWrite() {<br />
Writecount--; Writeflag=0;<br />
if (Writecount>0)<br />
OKtoWrite.Signal();<br />
else<br />
OKtoRead.Signal();<br />
}<br />
INIT {Readcount=0;Writecount=0;}<br />
END StartWrite<br />
<strong>Systemsoftware</strong> - Lektion X 13<br />
Realisierung bedingter kritischer Abschnitte<br />
MONITOR M<br />
Deklaration der Monitordaten;<br />
Condition CV; /* für alle Bedingungen*/<br />
Signal-Variante I Signal-Variante II Signal-Variante III<br />
ENTRY P() { ENTRY P() { ENTRY P() {<br />
while (!B) while (!B) while (!B) {<br />
CV.Wait(); CV.Wait(); CV.Signal();<br />
if B break;<br />
CV.Wait();<br />
while CV.Signal(); }<br />
(CV.STATUS()!=0) } ....<br />
CV.Signal(); .... CV.Signal();<br />
} END M }<br />
.... ....<br />
END M<br />
END M<br />
<strong>Systemsoftware</strong> - Lektion X 14
Implementierungskonzept auf Semaphore-Basis<br />
Monitor<br />
Precompiler<br />
Conditionvariable.Wait()<br />
Conditionvariable.Signal()<br />
Conditionvariable.Status()<br />
Precompiler<br />
Modul mit Semaphore-Operationen<br />
Semaphore-<br />
Operationen<br />
• pro Monitor:2 Semaphore für den Monitorein- und austritt<br />
• pro Condition-Variable: ein Semaphore und ein Zähler<br />
<strong>Systemsoftware</strong> - Lektion X 15<br />
Transformation eines Monitors M<br />
MODULE M<br />
Monitordaten;<br />
Semaphore M_Mutex, M_Urgent;<br />
int M_Urgentcount;<br />
......<br />
ENTRY F(Parameter) {<br />
P(M_Mutex);<br />
Anweisungsteil;<br />
if (M_Urgentcount>0) V(M_Urgent);<br />
else V(M_Mutex);<br />
}<br />
Weitere Monitorprozeduren;<br />
INIT {M_Mutex=1;M_Urgent=0;M_Urgentcount=0;....}<br />
END M<br />
<strong>Systemsoftware</strong> - Lektion X 16
Implementierung von Condition-Variablen und<br />
Statusabfrage<br />
Condition CV;<br />
Semaphore CV=0;<br />
int CV_Count=0;<br />
S=CV.Status();<br />
S=CV_Count;<br />
<strong>Systemsoftware</strong> - Lektion X 17<br />
Signal/Wait für Signal-Variante I<br />
CV.Wait();<br />
CV.Signal();<br />
CV_Count++;<br />
if (M_Urgentcount>0)<br />
V(M_Urgent);<br />
else V(M_Mutex);<br />
P(CV);<br />
P(M_Urgent);<br />
M_Urgentcount--;<br />
if (CV_Count>0) {<br />
V(CV);<br />
CV_Count--;<br />
M_Urgentcount++;<br />
}<br />
<strong>Systemsoftware</strong> - Lektion X 18
Signal/Wait für Signal-Variante II<br />
CV.Wait();<br />
CV.Signal();<br />
CV_Count++;<br />
if (M_Urgentcount>0)<br />
V(M_Urgent);<br />
else V(M_Mutex);<br />
P(CV);<br />
P(M_Urgent);<br />
M_Urgentcount--;<br />
while (CV_Count>0) {<br />
V(CV);<br />
CV_Count--;<br />
M_Urgentcount++;<br />
}<br />
<strong>Systemsoftware</strong> - Lektion X 19<br />
Signal/Wait für Signal-Variante III<br />
CV.Wait();<br />
CV.Signal();<br />
CV_Count++;<br />
if (M_Urgentcount>0)<br />
V(M_Urgent);<br />
else V(M_Mutex);<br />
/*Prozeß verläßt Monitor*/<br />
P(CV);<br />
/*Prozeß betritt Monitor*/<br />
CV_Count--;<br />
M_Urgentcount++;<br />
if (CV_Count>0)<br />
{<br />
V(CV);<br />
P(M_Urgent);<br />
}<br />
M_Urgentcount--;<br />
<strong>Systemsoftware</strong> - Lektion X 20
Vorgeschlagene Erweiterungen des<br />
Monitorkonzeptes<br />
• Prioritätsparameter für Signal und Wait<br />
Conditionvariable.Wait(Priorität)<br />
(Bedeutung: Einordnung des Prozesses in die Warteschlange der Condition-<br />
Variablen nach absteigenden Prioritäten)<br />
<strong>Systemsoftware</strong> - Lektion X 21<br />
Beispiel: Weckdienst (1)<br />
Client<br />
Timer<br />
periodisches<br />
Signal<br />
Wakeme<br />
Tick<br />
Clock-<br />
Monitor<br />
<strong>Systemsoftware</strong> - Lektion X 22
Beispiel: Weckdienst (2)<br />
MONITOR Clock<br />
int now; /*Absolutzeit*/<br />
Condition Wakeup;<br />
ENTRY WakeMe (int N) { /*N=relative Weckzeit*/<br />
int next;<br />
next=now+N;<br />
while (now
Beispiel: Plattenkopfsteuerung (2)<br />
MONITOR DiscHead<br />
int HeadPos; /*0..Cylmax*/<br />
enum {Up,Down} Direction;<br />
enum {nein,ja} Busy;<br />
Condition UpSweep,DownSweep;<br />
ENTRY Request(int Dest) {<br />
if (busy==ja) {<br />
if (Direction==Up) {<br />
if (HeadPos=Dest)<br />
DownSweep.Wait(Cylmax-Dest);<br />
else UpSweep.Wait(Dest);<br />
}<br />
}<br />
Busy=ja;<br />
HeadPos=Dest;<br />
}<br />
<strong>Systemsoftware</strong> - Lektion X 25<br />
Beispiel: Plattenkopfsteuerung (3)<br />
ENTRY Release() {<br />
Busy=nein;<br />
if (Direction==Up) {<br />
if (UpSweep.Status()!=0)<br />
UpSweep.Signal();<br />
else {<br />
Direction=Down;<br />
DownSweep.Signal();<br />
}<br />
else {/*Direction==Down*/<br />
if (DownSweep.Status()!=0)<br />
DownSweep.Signal();<br />
else {<br />
Direction=Up;<br />
UpSweep.Signal();<br />
}<br />
}<br />
INIT {<br />
HeadPos=0;<br />
Direction=Up;<br />
Busy=nein;<br />
}<br />
END Release<br />
<strong>Systemsoftware</strong> - Lektion X 26
Problem der geschachtelten Monitoraufrufe<br />
Monitor A<br />
B.P(..);<br />
Monitor B<br />
Prozedur P<br />
CV.Wait();<br />
Der Monitor A bleibt<br />
für die Wartezeit des<br />
Threads an der<br />
Condition-Variablen CV<br />
blockiert<br />
<strong>Systemsoftware</strong> - Lektion X 27