57
Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 14.01.2013 1 Computer-Systeme Teil 14: Synchronisation Überarbeitete Version

Computer-Systeme Teil 14: Synchronisationwi.f4.htw-berlin.de/users/messer/LV/WI-GWI-RABS/Folien/CS-14/14-CS... · Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 3 Übersicht

  • Upload
    lyngoc

  • View
    213

  • Download
    0

Embed Size (px)

Citation preview

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 14.01.2013 1

Computer-Systeme

Teil 14: Synchronisation

Überarbeitete Version

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 2

Literatur

http://de.wikipedia.org/wiki/Semaphor_(Informatik)[14-5]

Tanenbaum, Andrew: Moderne Betriebssysteme. 2. Auflage, Hanser, 1995

[14-4]

Siegert, Hans-Jürgen; Baumgarten, Uwe: Betriebssysteme. 5. Auflage, Oldenbourg, 2001

[14-3]

Dannegger, Christian; Geugelin-Dannegger, Patricia: Parallele Prozesse unter UNIX. Hanser, 1991

[14-2]

Werner, Dieter: Theorie der Betriebssysteme. Hanser, 1992[14-1]

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 3

Übersicht

• Grundbegriffe• enter und leave• Dekker's Algorithmus• lock und unlock• Semaphoren• Monitore

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 4

Hinführung I

• In diesem Teil werden grundsätzliche Prinzipien bzw. Probleme von Parallelität von Operationen auf gemeinsam benutzte Betriebsmittel, insbesondere RAM betrachtet.

• Bisher gingen wir von folgender Struktur aus:

• Alle Geräte (ION) können per DMA auf den RAM zugreifen und Interrupts senden.

RAM

CPU IOnIO2IO1

Bus

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 5

Hinführung II

• Nun verallgemeinern wir auf beliebig viele CPUs:

• Der RAM mit dem Bus bietet atomare, also unteilbareLese/Schreib-Operationen an, die nur sequentiell ablaufen. D.h. zu einem Zeitpunkt kann immer nur eine CPU/Gerät auf den RAM zugreifen. Alle anderen Geräte/CPUs müssen warten.

RAM

CPU1 CPU2 CPUn

Bus

IOnIO2IO1 ……

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 6

Annahmen I

• Alle Instruktionen der CPUs sind durch Interrupts nicht unterbrechbar, d.h. wenn eine CPU einen Interruptfeststellt, so führt sie die aktuelle Instruktion vollständig aus bevor sie mit der Behandlung des Interrupts beginnt.

• Während einer Instruktion hat die CPU die volle Kontrolle über den Bus bzw. Zugriff auf den RAM, d.h. niemand kann den Bus der CPU wegnehmen noch parallel benutzen.

• Dass heißt:– Für 1-CPU-Maschinen: Nur zwischen den Instruktionen kann

ein Threadwechsel stattfinden, keine Parallelität– Für N-CPU-Maschinen: Für jede einzelne CPU kann nur

zwischen den Instruktionen ein Threadwechsel stattfinden, aber untereinander haben alle CPUs volle Parallelität

• Hinweis: Per Timer-Interrupt kann ein Thread seine CPU verlieren.

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 7

Annahmen II

• Für DMA-fähige Geräte gilt folgendes:– Der Vorgang des Kopierens von Blöcken in oder aus dem RAM wird

in Teile zerlegt.– Für jeden Teil erhält das Gerät den Bus atomar.

• Grund: Wenn der vollständige DMA-Vorgang den Bus belegen würde, würden die Wartezeiten der anderen Geräte/CPUs auf den Bus zu lange dauern.

• Nicht-DMA-fähige Geräte brauchen wir hier nicht zu betrachten, denn diese greifen nicht auf den RAM zu.

Aus Gründen der Vereinfachung betrachten wir in diesem Teil nurdie Zugriffe auf den RAM. Dieselben Probleme treten aber auchbeim Zugriff auf Plattenblöcke etc. auf.

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 8

Hinführung III

Assertiona != 0

Assertiona= a'-1

.......b:= a;......b:= b-1;......a:= b;.......

......IF a != 0 THEN

......b:= c/a;......

FI.......

Thread A Thread B

Variable a

Zugriff

KritischeAbschnitte

Falls vorhera = 1 war ...

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 9

Bemerkungen

• Assertion = Zusicherung = Bedingung, die bei einem korrekten Programm immer erfüllt sein muss

• Um Probleme erkennen zu können, sollte folgendes angenommen werden:– Threads können aufgrund von Pausen andere überholen.– Threads können unterschiedliche Geschwindigkeiten haben.

• Zur Prüfung auf Korrektheit sind auch pathologische, gemeine Konstellationen auszudenken.

• Gibt es eine Konstellation, die zu einem Fehler führt, dann ist die Software fehlerhaft, auch dann, wenn die Wahrscheinlichkeit für derartige Probleme minimal ist.

• Ein Fehler liegt immer dann vor, wenn eine Zusicherung verletzt wird – dies gilt auch dann, wenn explizit keine Zusicherungen benutzt werden.

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 10

Das Problem

a:= 1;......

b:= a;......b:= b-1;

IF a != 0 THENa:= b;......

......b:= c/a;......

FI......

Das kann bei einer wie auch bei mehreren CPUs passieren.

Thread A Thread B

Bedeutet "Pause"

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 11

Kritische Abschnitte I

• Thread = Sequentiell ablaufende Software ohne eigenen, von anderen Threads getrennten Adressraum, d.h. alle Threadsteilen sich einen AdressraumJeder Thread kann auf alle Variablen aller anderen Threadszugreifen.

• Kritischer Abschnitt = Bereich im Code, bei dessen Ausführung Probleme mit anderen Threads auftreten können

In der Literatur wird häufig statt von Threads von Prozessen gesprochen, dann haben auch Prozesse diese Probleme.

Allgemein: Immer wenn Prozesse/Threads auf gemeinsameBetriebsmittel zugreifen, gibt es Abstimmungsprobleme.

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 12

Kritische Abschnitte II

• Kritische Abschnitte sind Code-Abschnitte, die (fast) nie gleich sind.

• Kritische Abschnitte beziehen sich immer auf Daten (Variablen, Geräte etc.).

• Alle kritischen Abschnitte, die sich auf dieselbe Menge von Variablen beziehen, werden zu einer Klasse zusammen gefasst.Mit anderen Worten: Wenn an mehreren Stellen auf dieselben Variablen aus verschiedenen Threads zugegriffen wird, so bilden alle diese Stellen jeweils kritische Abschnitte einer Klasse.

• Alle kritischen Abschnitte einer Klasse müssenuntereinander koordiniert werden.

• Kritische Abschnitte verschiedener Klassen brauchen nicht koordiniert zu werden.

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 13

Begriffe - Ganz allgemein

• Koordination = Abstimmung zwischen Threads, um Datenkonsistenz bei gleichzeitigem Zugriff zu erhalten

• Datenkonsistenz = Erfüllen von für die Problemlösung notwendigen Bedingungen an Datenwerte – die Assertions

• Synchronisation =– zeitliche Abstimmung hinsichtlich der Benutzung von

Ressourcen– Herstellen von "Gleichzeitigkeit"

• Ressource = Betriebsmittel = Hier: Adressierbarer SpeicherAllgemein: Etwas, was belegt oder verbraucht werden kann,z.B. CPU, Netz, Platte, Drucker (Papier)

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 14

Wechselseitiger Ausschluss

• Wechselseitiger Ausschluss = Mutual Exclusion = Ergebnis der Koordinierung zur Verhinderung von Problemen bei der gemeinsamen Benutzung von Variablen in kritischen Abschnitten

• Beim wechselseitigen Ausschluss werden Threads daran gehindert, eine Ressource zu benutzen, wenn diese durch einen anderen Thread belegt ist.Ressource ist hier die Menge der gemeinsam benutzten Variablen einer Klasse.

• Erst nach Freigabe kann ein anderer Thread die Ressource belegen.

• Wechselseitiger Ausschluss ist das Mittel, um Synchronisation zu realisieren.

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 15

Probleme des wechselseitigen Ausschlusses

• Deadlock = Warten auf ein Ereignis, das nicht eintreten kann

• Deadlock ist ein strukturell logisches Problem,Beispiel: You-after-you-Problem

• Starvation = Zu langes Warten auf ein mögliches Ereignis bzw.übermäßige Ungerechtigkeit zwischen Threads

• Starvation ist ein Scheduling-Problem, d.h. ein Problem der schlechten Zuweisung von Ressourcen an Threads (Scheduling)

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 16

Demonstrationsbeispiel – Dining Philosophers I

• Ein Philosoph isst entweder Spaghetti oder er denkt.Essen und Denken müssen sich abwechseln und nicht zu lange dauern(in beiden Fällen drohen sonst gesundheitliche Schäden).

• Philosophen benötigen zum Essen zwei Gabeln (Erziehung).• Der Topf der Spaghetti ist unendlich groß.

Spaghetti

Philosoph 1

Philosoph 2

Philosoph 3

Philosoph 4

Gabel 4

Gabel 3Gabel 2

Gabel 1

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 17

Demonstrationsbeispiel – Dining Philosophers II

• Alle Philosophen benutzen denselben Algorithmus.• Zum Deadlock führt folgendes:

– Jeder nimmt die Gabel rechts.– Jeder wartet auf die Gabel links.

• Zu Starvation führt folgendes:– Jeder nimmt die Gabel rechts.– Wenn die fehlende Gabel links nicht verfügbar ist, legt er die rechte

Gabel zurück.– Es beginnt von vorn.

• Hinweise– Das Beispiel stammt von Edsger Dijkstra (1965)– Siehe http://en.wikipedia.org/wiki/Dining_philosophers_problem– Ursprünglich war es ein chinesisches Gericht und die Gabeln waren

Stäbchen.

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 18

Zeitpunkte der Synchronisation

• Vor dem kritischen Abschnitt ("pessimistische" Strategie)Vor dem Betreten wird sichergestellt, dass später keine Probleme auftreten können.

Beispiele: Semaphoren, Lock/Unlock

• Im kritischen Abschnitt ("optimistische" Strategie)Während der Aktivitäten innerhalb des kritischen Abschnittes wird auf Probleme geprüft.Gibt es sie, werden Verfahren durchgeführt, die den alten Zustand vor dem Konflikt wieder herstellen,und alles beginnt von vorn.

Beispiele: Ethernet, Transaktionen (Datenbanken)

Wir beschäftigen uns hier nur mit der ersten Gruppe.

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 19

Ebenen der Implementierungen

• Wir beginnen mit den einfachen Mechanismen und schreiten dann weiter in Richtung Komplexität voran.

• Einfach sind:– Algorithmus nach Dekker– Test-and-Set-Instruktionen zusammen mit Busy Waiting

Zusammengesetzte Mechanismen

Komplexe Mechanismen

Einfache Mechanismen

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 20

Kritischer Abschnitt I

....

.... Code ....

....enter(Klassenname);

.... Code ....

....

.... Code ....leave(Klassenname);........ Code ........

PrologVerfahren zur Koordinierung

EpilogVerfahren zur Freigabe

• Aus Gründen der Vereinfachung wird von zwei Threads A und B ausgegangen.

• Der Code in Freistilnotation ist auf diese Situation abgestimmt.• In der Praxis muss für jede Klasse ein abstrakter Datentyp mit

eigenen lokalen Variablen etc. benutzt werden.

Kritischer Abschnitt (grau)

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 21

Kritischer Abschnitt II

• In den beiden Routinen enter() und leave() wird ein Verfahren abgearbeitet, das die Synchronisation realisiert:

• Die Parameter (Klassenname) von enter() und leave() beziehen sich auf die Klasse der kritischen Abschnitte.

• Implementierungstechnisch sind dies Variablen (von einem Typ, der die Synchronisation realisiert), mit denen die Koordinierung durchgeführt wird.

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 22

Implementierungen von enter() und leave()

• Es gibt verschiedene Versionen für die Implementierungen, die jeweils Stärken und Schwächen haben.

• Es werden im folgenden zwei betrachtet.

• Dies beginnt mit einer schrittweisen Entwicklung des Algorithmus von DekkerIn den ersten Versionen sind Fehler, die in den späteren bereinigt werden.(siehe http://en.wikipedia.org/wiki/Dekker's_algorithm)

Bei diesen Algorithmen wird von zwei Threads und nur einemkritischen Abschnitt ausgegangen, so dass die Parameter für enter()und leave() wegfallen können, d.h. es gibt nur eine Klasse.

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 23

Dekker's Algorithmus I – 1. Versuch

enter() {WHILE turn = B DOOD;

}

leave() {turn:= B;

}

enter() {WHILE turn = A DOOD;

}

leave() {turn:= A;

}

Thread A Thread B

turn ist eine globale Variable, die initial auf A gesetzt ist.

Jeder Prozess gibt seinem Partner nach seiner Arbeit das Recht, denAbschnitt zu betreten – echt fair.

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 24

Dekker's Algorithmus II - Beurteilung

• Sieht eigentlich ganz gut aus, aber...• Problem 1: Wenn ein Prozess außerhalb des kritischen

Abschnittes beendet wird, entstehen Deadlocks.

Warum?Wenn die Variable turn(Klassenname) den Wert A hat und der Thread A nicht mehr existiert, dann kann B nie wieder in den kritischen Abschnitt, denn B wartet auf etwas, was nie eintreten wird, nämlich dass A etwas tut.

Die Idee des 2. Versuchs besteht darin, nicht mehr festzulegen,wer als nächstes eintreten kann, sondern wer eingetreten möchte.

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 25

Dekker's Algorithmus III - 2. Versuch

enter() {A-will:= true;WHILE B-will DOOD;

}

leave() {A-will:= false;

}

enter() {B-will:= true;WHILE A-will DOOD;

}

leave() {B-will:= false;

}

Thread A Thread B

Die beiden boole'schen Variablen A-will und B-will bildendie Klassenvariablen, initial sind beide false.Sie können atomar gelesen und geschrieben werden.

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 26

Dekker's Algorithmus IV - Beurteilung

• Funktioniert ganz gut, aber....• Problem 2:

Es entstehen durch exakte Parallelität Deadlocks.

Idee: Die Deadlocks lassen sich durch zeitweises Zurücknehmender Willenserklärung auflösen...

A-will:= true;WHILE B-will DOOD;

B-will:= true;WHILE A-will DOOD;

parallel

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 27

Dekker's Algorithmus V - 3. Versuch

enter() {A-will:= true;WHILE B-will DO

A-will:= false;// Chance für BA-will:= true;

OD;}

leave() {A-will:= false;

}

enter() {B-will:= true;WHILE A-will DO

B-will:= false;// Chance für AB-will:= true;

OD;}

leave() {B-will:= false;

}

Thread A Thread B

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 28

Dekker's Algorithmus VI - Beurteilung

• Bisher beste Lösung, aber...• Problem 3: Es kann Verhungern auftreten.

Warum?Wenn A viel schneller als B ist, dann nutzt A seine Chance nach der Freigabe durch B aus – B muss dann warten.Wenn dann A den Abschnitt verlässt und dann gleich wieder betritt, kann nun auch wieder A sich aufgrund der höheren Geschwindigkeit gegenüber B durchsetzen – Starvation für B.

Idee: Das bisherige durch die Priorisierung aus dem 1. Versuchkombinieren, d.h. derjenige, der warten muss, hat beim nächstenMal Priorität…

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 29

Dekker's Algorithmus - Die beste Lösung

enter() {A-will:= true;WHILE B-will DO

IF turn = B THENA-will:= false;WHILE turn = B DO OD;A-will:= true;

FI;OD;

}

leave() {turn:= B; A-will:= false;

}

enter() {B-will:= true;WHILE A-will DO

IF turn = A THENB-will:= false;WHILE turn = A DO OD;B-will:= true;

FI;OD;

}

leave() {turn:= A; B-will:= false;

}

Thread A Thread B

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 30

Bemerkungen

• Der vorgestellte Algorithmus hat die Eigenschaft,– dass er bei N-CPUs funktioniert, d.h. immer.– dass der wartende Thread Zeit in einer Schleife vertrödelt –

dies wird Busy Waiting genannt.

• enter() und leave() mit einer Implementierung, die BusyWaiting arbeitet, werden auch lock() und unlock() genannt.

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 31

• In der Praxis wird mit speziellen Instruktionen gearbeitet:Eine Test-and-Set-Instruktion liest, modifiziert und kopiert den alten Inhalt ununterbrechbar durch andere CPUs/Geräte.

• Was macht die Instruktion?Der 2. Parameter gibt die Adresse einer Speicherzelle an. Von dort wird der Wert gelesen und dann auf true (oder 1) gesetzt.

• Technisch wird dies über ein 1 Bit realisiert: dieses Bit wird auf 1 gesetzt und der frühere Wert wird in ein Register geschrieben.

Ununterbrechbare test-and-set-Instruktion I

Instruction TestAndSet(Addr b) {old:= b; // der alte Wert an Adresse bb:= true; // an die Adresse b wird true geschriebenreturn(old); // der ursprüngliche Wert wird geliefert

}

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 32

Ununterbrechbare test-and-set-Instruktion II

Instruction TestAndSet(Addr b) {old:= b;b:= true; return(old);

}

enter(class) {crit:= true;WHILE crit DO

crit:= TestAndSet(class);OD

}

leave(class) {class:= false;

}

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 33

enter()/leave() auf einem 1-CPU-System I

• Bei 1-CPU-Maschinen kann ein Wechsel der CPU zu einem anderen Thread innerhalb des kritischen Abschnitts nur nach einen Interrupt erfolgen.

• Zur Erinnerung: Ein Interrupt-Handler kann den Scheduleraufrufen, der dann die CPU einem anderen Thread zuweist.

• Daher gibt es die Nahe liegende, aber problematische Implementierung:

• Durch dieses Ausschalten der Unterbrechungen behält der aktuell laufende Thread in jedem Falle seine CPU und kann daher ungestört den kritischen Abschnitt durchlaufen.

enter(class) {disable_interrupts();

}

leave(class) {enable_interrupts();

}

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 34

enter()/leave() auf einem 1-CPU-System II

• Da das Ausschalten von Unterbrechungen zu Problemen aufgrund von Verlust von Interrupts führt, werden gezielt bestimmte Interrupt-Level (Prioritäten) verwendet:– Die CPU erhält einen Level.– Ein Interrupt kommt nur dann durch, wenn sein Level höher als

der der CPU ist.– Normalerweise ist der CPU-Level auf 0.

• Es wird dann nur soviel, wie unbedingt nötig gesperrt.• Das Abschalten der Interrupts ist eigentlich falsch, denn es

muss nur ein Threadwechsel (continue()) sowie das Ändern von Daten in den kritischen Abschnitten verhindert werden.

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 35

Alternative Implementierungen von enter/leave()

enter()/leave()

Busy Waiting1..N CPUsSpezialinstruktionenInterrupts erlaubt

Busy Waiting1..N CPUs

Interrupts erlaubt

Kein Busy Waiting1 CPU

Interrupts verboten

Dekker Spezialinstruktionen Disable Interrupts

Wenn enter() und leave() mit einer dieser Methoden implementiertwerden, so sollen diese lock() und unlock() genannt werden.

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 36

Wir haben zwei Probleme…

• Das Busy Waiting ist CPU-Zeit-Verschwendung.Hier wäre es gut, im Wartefall per continue() einen anderen Thread zu aktivieren.

• Ohne Busy Waiting geht es nur mit Abschalten der Interrupts und nur bei einer CPU. Das hat aber den möglichen Verlust von Interrupts zur Folge.

• Am besten ist es, ohne Abschalten von Interrupts die CPU effizient zu nutzen.

Genau hierzu hatte Edsger Dijkstraeine Idee: Semaphoren.

Damit betreten wir den Ebene derkomplexen Mechanismen.

Zusammengesetzte Mechanismen

Komplexe Mechanismen

Einfache Mechanismen

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 37

Semaphoren - Die Idee

• Anstatt den gesamten kritischen Abschnitt mit lock() und unlock() ineffizient zu schützen, wird damit nur das Innere von enter() und leave() geschützt.

• Der kritische Abschnitt ist dann immer noch geschützt, wird aber wie normaler Code ausgeführt.

• Wir haben damit zwei Stufen:– Innerhalb von enter() und leave()– Zwischen enter() und leave()

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 38

Semaphoren - (Eisenbahn-)Signale I

• Eine Semaphore S besteht aus:– Es gibt eine boole'sche Variable state zur Repräsentation des

Belegungszustandes: true heißt frei, false belegt.Diese hat initial als Wert ein true.

– Weiterhin gibt es eine Warteschlange q mit den wartenden Threads ohne eine Priorität.Diese Warteschlange ist initial leer.

• Operationen auf der Semaphore S:– p(S) realisiert das Betreten

p steht für passeer, probeeren (Niederländisch). – v(S) realisiert das Verlassen

v steht für vrijgeven, verhogen (Niederländisch).

Diese Art der Semaphoren wird binär genannt, da es nur zweiZustände für den Zustand state gibt.

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 39

Semaphoren - (Eisenbahn-)Signale II

• Operationen auf der Warteschlange q:– enqueue():

Schlafen legen des Aufrufers (continue()) und Einreihen in eine Warteschlange

– dequeue():Irgendein Thread wird aus der Warteschlange geholt und fortgesetzt

– empty():Abfrage, ob Warteschlange leer ist

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 40

Benutzung der Semaphoren I

....

.... Code ....

....enter(Klassenname);

.... Code ....

....

.... Code ....leave(Klassenname);........ Code ........

....

.... Code ....

....p(Klassenname);

.... Code ....

....

.... Code ....v(Klassenname);........ Code ........

Kritische Abschnittemit Busy Waiting Eigentlicher

kritischer Abschnitt

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 41

Benutzung der Semaphoren II

• Im Bereich mit der Farbe Lila können mehrere Threadsparallel arbeiten.

• Im hellgrauen Bereich wird mit Busy-Waiting erreicht, dass nur ein Thread zu einem Zeitpunkt arbeiten kann.

• Im dunkelgrauen Bereich kann dank p() und v() nur ein Thread zu einem Zeitpunkt arbeiten, ohne dass BusyWaiting erfolgt.

Durch dieses Verfahren wird der Bereich des Busy Waitingserheblich reduziert und damit effizienter gemacht.

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 42

Implementierung der Semaphoren I

p(Semaphor S) {lock(S);IF S.state THEN S.state:= false;

ELSE S.enqueue();FI;unlock(S);

}

v(Semaphor S) {lock(S);IF S.empty()THEN S.state:= true;

ELSE S.dequeue(); FI;unlock(S);

}

KritischerAbschnitt

KritischerAbschnitt

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 43

Implementierung der Semaphoren II

• Wenn die Variable state true ist, heißt das, dass der kritische Abschnitt leer ist und betreten werden kann.

• Nach einem dequeue() laufen eventuell zwei Threadsparallel:– Der Thread, der das dequeue() ausgeführt hat– Der Thread, der durch das dequeue() aus der Warteschlange

geholt wurde• Der frisch aus der Warteschlange geholte läuft direkt nach

dessen früheren enqueue() weiter.• Alle Prozesse führen denselben Code aus, d.h. kein separater

Code wie in dem Beispielverfahren von Dekker.

• Damit keine Deadlocks auftreten:– enqueue() macht direkt vor dem Suspendieren ein unlock(S)– dequeue() macht direkt nach dem Wiederanlaufen ein lock(S)

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 44

Implementierung der Semaphoren III

enqueue(Semaphor S) {Sich selbst in die Queue eintragenIn Thread-Tabelle auf "Waiting" setzenunlock(S);continue(Scheduler);lock(S);

}

dequeue(Semaphor S) {Einen Thread aus der Queue holenIn Thread-Tabelle auf "Ready" setzen

}

Wiederaufsetz-punkt nach demWarten

Jetzt erst Abgabeder Kontrolle

Aufgrund dieses lock(S)wartet derfrisch aufgeweckte Thread darauf, dasssein Aufwecker das v() verlässt

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 45

Monitore I

• Das Programmieren mit Semaphoren ist – aufwändig– relativ fehlerhaft, da die p() und v() über den Code verteilt sind

und manchmal ein v() oder ein p() vergessen oder zuviel ausgeführt wird.

• Idee:In die Programmiersprache ein "sicheres" Konstrukt integrieren und den Compiler die p()- und v()-Operationen generieren lassen: der Monitor

Zusammengesetzte Mechanismen

Komplexe Mechanismen

Einfache Mechanismen

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 46

Monitore II

• Monitor = Abstrakter Datentyp mit allen für eine Klasse vorhandenen Operationen sowie der Bedingung, dass immer nur ein Thread eine der Operationen ausführen kann.

• Hat ein Thread den Monitor betreten, so gehört er ihm bis er ihn verlassen hat oder in einer Warteschlange wartet.

• Die Idee stammt von C.A.R HoareSiehe http://de.wikipedia.org/wiki/Monitor_(Informatik)

• Eine gute Implementierung stammt von Per Brinch-Hansen: realisiert in CPascal

• Für Java dienten diese Monitore als Vorlage für die Thread-Implementierung.

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 47

Monitore III

MONITOR Name {Deklaration der lokalen VariablenOperation-1(Parameter) {

....}Operation-2(Parameter) {

....}....Operation-N(Parameter) {

....}Initialisierung der lokalen Variablen

}

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 48

Monitore II

• Entry Queue = Threads, die den Monitor betreten wollen, aber nicht dürfen

• Condition Queues = Hier warten Threads auf bestimmte Ereignisse

• Urgent Queue: Stack für kurzzeitig wartenden Prozesse

Entry Queue

Monitor

Urgent Queue

Condition Queues

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 49

Bedingungsvariablen I

• Bedingungsvariable = logische Variable, deren Zustand an eine Bedingung gekoppelt ist:– True -> Bedingung erfüllt– False -> Bedingung nicht erfüllt

• Die Bedingung selbst wird so in den Code gesteckt, dass bei der Erfüllung der Bedingung die Operation signalcond() ausgeführt wird.

• Das Warten auf die Erfüllung der Bedingung wird durchwaitcond() initiiert.

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 50

Bedingungsvariablen II

• Waitcond(Bedingungsvariable)bringt den aufrufenden Thread in die Warteschlange für diese Variable und gibt damit Monitor vorübergehend frei

• Signalcond(Bedingungsvariable)holt den am längsten wartenden Thread aus der Warteschlange, aktiviert ihn und setzt den Aufrufer in die Urgent-Queue

Der Aufrufer wird erst dann wieder aktiviert, wenn der von ihm befreite Thread den Monitor verlässt oder ihn durch Eintreten in eine Warteschlange vorübergehend frei gibt.

Operationen auf Bedingungsvariablen

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 51

Reader/Writer mit Monitoren I

Thread P1 Thread P2 ReaderWriter

Zirkulärer Puffer

• Writer:– In einen freien Bereich werden Daten geschrieben.– Dann werden diese vom Writer für den Reader frei gegeben.

• Reader:– Die vom Writer geschriebenen Daten werden entnommen.– Der nun ausgelesene Bereich wird für den Writer frei gegeben.

Reader/Writer-Mechanismen gehören zu den Standard-Verfahrender Inter-Prozess-Kommunikation.

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 52

Idee des Zirkulären Puffers I

Out

Invom Writerbewegt

vom Readerbewegt

Noch nichtverarbeitet

Basis

Limit

Zeigt auf nächstesByte (read)

Zeigt auf nächstes

Byte (write)

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 53

Idee des Zirkulären Puffers II

• Es gibt zwei Zeiger, die als Index in einem Array fungieren:– Der In-Zeiger zeigt auf das Array-Element, das als nächstes

vom Writer beschrieben wird, das erste freie Element also.– Der Out-Zeiger zeigt auf das Array-Element, das als nächstes

vom Reader gelesen werden soll, also das nächste Element.

• Die Variable count gibt die Belegung des Puffers wieder.• MOD ist der Modulo-Operator, dessen Anwendung dafür

sorgt, dass beide Zeiger In und Out sich immer innerhalb der erlaubten Array-Grenzen bewegen.

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 54

Reader/Writer mit Monitoren II – Teil 1

MONITOR Buffer {elem[0..size-1] Buffer;INT count;INT In, Out; CONDITION NonEmpty, NonFull;

writeBuffer(elem what) {IF count = size THEN WAITCOND(NonFull); FIBuffer[In]:= what;In:= (In+1) MOD size;count++;SIGNALCOND(NonEmpty);

}

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 55

Reader/Writer mit Monitoren III – Teil 2

Elem readBuffer(){IF count = 0 THEN WAITCOND(NonEmpty); FIwhat:= Buffer[Out];Out:= (Out+1) MOD size;count--;SIGNALCOND(NonFull);return(what);

}

/* Initialisierung */Count:= In:= Out:= 0;

}

Dies ist eine typische Ring-Puffer-Lösung zur Interprozesskommunikation.

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 56

Bemerkungen

• Es gibt zwei Bedingungsvariablen:– NonEmpty symbolisiert die Bedingung, dass der Puffer nicht

leer ist, d.h. es ist irgendetwas enthalten– NonFull symbolisiert die Bedingung, dass der Puffer nicht

vollständig gefüllt ist, d.h. es gibt noch Platz

• Wenn nun ein Thread etwas in den Puffer schreiben will, muss vorher Platz da sein. Ist der Puffer voll, legt er sich aufdas Ereignis, dass mindestens für ein Element Platz ist, schlafen.

• Wenn ein Thread etwas aus dem Puffer lesen will, muss mindestens ein geschriebener Eintrag vorhanden sein. Wenn nicht, so legt er sich auf das Ereignis schlafen, dass etwas in den Puffer geschrieben wurde.

Computer-Systeme – WS 12/13 - Teil 14/Synchronisation 57

Nach dieser Anstrengung etwas Entspannung....