02.11.2013 Views

Systemsoftware

Systemsoftware

Systemsoftware

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!