Nsp3.21 3.2 Bedingungssynchronisation Motivation: Wenn für eine Operation auf einem Objekt die Voraussetzung nicht erfüllt ist, ist es häufig angebracht,

Slides:



Advertisements
Ähnliche Präsentationen
der Universität Oldenburg
Advertisements

Monitore in Java++ Aufgabe 2 von Markus Schlebusch Christoph Reinboth Sebastian Zok Johannes Stolte Norman Zuther.
Klassen - Verkettete Liste -
10.2 Wechselseitiger Ausschluss in Hardware
Nsp Semaphore sind einfache Synchronisationsobjekte, ähnlich wie Ereignisse, aber unabhängig von Monitoren: (das) Semaphor: altes Flügelsignal.
6.3 Ereignisbasierte Systeme Ereignis (event) : eine Ereignis-Quelle (event source, publisher) generiert Benachrichtigung (event notification), an der.
3 Prozessverwaltung  sieht einen Prozess als Objekt der Verwaltung,
Terminierung und Deadlocks Enkhbat Daginaa Betreuerin Prof. Heike Wehrheim Totale Korrektheit.
Kapitel 6.1 Nebenläufigkeit und wechselseitiger Ausschluss
Ausnahmen HS Merseburg (FH) WS 06/07.
Threads Richard Göbel.
Java: Dynamische Datentypen
Indirekte Adressierung
Java: Referenzen und Zeichenketten
Kapitel 10 Nebenläufigkeit und wechselseitiger Ausschluss
Nebenläufige Programmierung
1 Vorlesung Informatik 2 Algorithmen und Datenstrukturen (02 – Funktionenklassen) Prof. Dr. Th. Ottmann.
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (02 – Funktionenklassen) Tobias Lauer.
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (02 – Funktionenklassen) Prof. Dr. Th. Ottmann.
Benötigte Applets Startseite: in HTML-Format Applet auf der Startseite Das Applet, das auf der Startseite geladen wird, wird die vier Buttons und die eine.
1 Named Pipes alias FIFO Haben einen Eintrag im Dateisystem und sind somit durch Zugriffsrechte identifizierbar Ermöglichen die Kommunikation zwischen.
Nsp Nebenläufigkeit und Objektorientierung ! Hinterfragen: wie verhalten sich die Konzepte Prozesse und Synchronisation zu den KonzeptenKlassen.
3.1.7 Korrektheit von Objekten Voraussetzung für die Diskussion der Korrektheit von nichtsequentiell benutzten abstrakten Objekten: Modellbasierte Spezifikation:
PRJ 2007/1 Stefan Dissmann Motivation Problem: Benutztes Objekt kennt den Kontext seiner Nutzung nicht. Daher kann es in besonderen Situationen keine Entscheidung.
PRJ 2007/1 Stefan Dissmann Motivation Problem: gleiche Datenstrukturen werden für verschiedene Objekte gebraucht: z.B. Listen von Studierenden, Kunden,
PKJ 2005/1 Stefan Dissmann Klassenhierarchie Person Kunde Goldkunde Lieferant Object.
DVG Interfaces. DVG mehrfache Vererbung 4 Mehrfache Vererbung ist die Ableitung einer Klassen von mehreren anderen Klassen. –farbigerPunkt.
DVG Klassen und Objekte
EDV Parallelprogrammierung1 Parallelprogrammierung mit JAVA.
Seite 1 Interface - Konzept Ein Interface führt einen neuen Datentyp ein: interface Frau {... } Das Interface enthält Deklarationen ( keine Definitionen.
Grundkonzepte Java - Klassendefinition
Javakurs FSS 2012 Lehrstuhl Stuckenschmidt
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fachbereich.
Einführung in die Programmierung Wintersemester 2009/10 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund.
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fachbereich.
Javakurs FSS 2012 Lehrstuhl Stuckenschmidt
Parallel Matrix Multiplication
Parallel Programming Condition Queues
Prozess-synchronisation
Thread Synchronisation in JAVA
Betriebssysteme Übung 2. Tutorium. Task 1 – Locks (1) Wozu Locks? Dienen dazu, exklusiven Zugriff auf eine Ressource sicherzustellen Lock = binäre Semaphore.
EPROG Tutorium #6 Philipp Effenberger
Learning By Doing Parallelverarbeitung Multithreading (Nebenläufigkeit) Alte Idee der Parallelverarbeitung statt rein sequentieller Prozesse Parallelverarbeitung.
Letzte Chance!!! Exceptions Thread, Runnable Synchronized Wait, notify, notifyAll Thread States Semaphoren JCSP Swing JOMP Linearizability History Amdahl‘s.
Java-Kurs - 8. Übung Besprechung der Hausaufgabe.
Threads in Java Wiederholung der BS Grundlagen Alois Schütte AOSD1.
Muster nebenläufiger Programmierung concurrent Packet von Java Alois Schütte AOSD1.
Java Syntaxdiagramme Buchstabe A B Z a z ... Ziffer
Robuste Programme durch Ausnahmebehandlung
Prof. Dr. Alois Schütte Advanced System Programming 1 Das concurrent Paket 1 Überblick 2 Lock 3 Condition 4 Queue 5 Executors.
7.2.4 Klassifikation mobilen Codes Nicht vergessen:  Sowohl das Fernkopieren als auch die Migration von Objekten setzt voraus, daß der Code entweder am.
2 Nebenläufige Prozesse. 2.1 Programmstruktur und Prozesse private Prozess = Anweisungen + Daten gemeinsame Aber:Wie verhält sich das Konstrukt „Prozess“
Ausnahmen Vorlesung besteht aus zwei Teilen Programmierung (4 SWS)
2 Datenabstraktion Geheimnisprinzip:
1.3 Verklemmungen Synchronisation löst Probleme – ist aber auch Gefahrenquelle: Prozeß wartet an Synchronisationspunkt – ist gesichert, daß er irgendwann.
Dynamische Prioritäten Statische Prozess-Prioritäten sind sinnvoll, falls Prozesse in wenige Klassen einteilbar (3.3.3) Dynamische Prioritäten.
3 Interaktion über Objekte. 3.1 Sperrsynchronisation dient der Vermeidung unkontrollierter nebenläufiger Zugriffe auf gemeinsame Datenobjekte und der.
1 3 Interaktion über Objekte Sperrsynchronisation dient der Vermeidung unkontrollierter nebenläufiger Zugriffe auf gemeinsame Datenobjekte und.
5 Implementierung von Prozessen und Synchronisationskonstrukten
4 Ablaufsteuerung. Ablaufsteuerung (scheduling) = Zuteilung von Betriebsmitteln (resources) – wiederverwendbaren oder verbrauchbaren – an Prozesse, z.B.
Threads in Java Threads  Sprachumfang von Java Der Java-Standard fordert nur die Unterstützung von Thread-Prioritäten. Es gibt keine Forderung bzgl.:
3.2 Bedingungssynchronisation Motivation: Wenn für eine Operation auf einem Objekt die Voraussetzung nicht erfüllt ist, ist es häufig angebracht, auf deren.
Parallel Programming Semaphores / Reader - Writer - Lock
Wieland Schwinger Softwareentwicklung 2 Assertions.
93 Das Monitorkonzept (nach Hoare/Brinch-Hansen 1974) Nur ein Prozess bzw. Thread kann zu einem bestimmten Zeitpunkt im Monitor aktiv sein => gegenseitiger.
1 VE 11 Kruskal-Realisierung Listen. 2 Auf dem Weg zur Kruskal-Realisierung Vorüberlegungen: Der Graph könnte dargestellt werden als Menge von Knoten,
, Dr. Wolfram Amme, Softwareentwicklung in Java, FSU Jena, WS 2005/06 1 Beispiel class SpreadSheet { int cellA1, cellA2, cellA3; synchronized.
, Dr. Wolfram Amme, Softwareentwicklung in Java, FSU Jena, SS Exceptions in der Programmiersprache Java.
1.Event Queue.
Zwei Denkansätze zur Klasse Schlange
 Präsentation transkript:

nsp Bedingungssynchronisation Motivation: Wenn für eine Operation auf einem Objekt die Voraussetzung nicht erfüllt ist, ist es häufig angebracht, auf deren Erfüllung zu warten, anstatt false zu liefern oder eine Ausnahme zu melden. Beispiele: Virtueller Drucker (3.1.1  ), Puffer(3.1.2  )

nsp Verzögerte Monitore Verzögerter Monitor (delayed monitor) = Monitor, in dem auf die Erfüllung einer Bedingung gewartet wird; beim Blockieren wird der Ausschluss aufgegeben, so daß ein anderer Prozess in den Monitor eintreten kann – dessen Aktionen vielleicht dazu führen, daß die Bedingung erfüllt ist; ein im Monitor blockierter Prozess kann frühestens dann fortfahren, wenn ein anderer Prozess den Monitor verlässt – oder selbst blockiert. Blockierte Prozesse haben Vorrang vor Neuankömmlingen.

nsp Warteanweisungen (Nicht Java!) Statement =... | AwaitStatement AwaitStatement = AWAIT Condition ; Diese Warteanweisung ist nur im statischen Kontext eines Monitors erlaubt, und die gemeinsamen Variablen in der Condition müssen Monitorvariable sein. Semantik:Wenn nach der Warteanweisung fortgefahren wird, ist die angegebene Bedingung garantiert erfüllt. Muß gewartet werden, wird der Monitor freigegeben. Fairness: blockierte Prozesse haben Vorrang (s.o.)

nsp3.24 Beispiel Drucker (3.1.1  ), hier nur mit request3.1.1 und vereinfachtem release : MONITOR Printer { private Thread owner; public void request() { AWAIT owner==null; owner = Thread.currentThread(); } public void release() { owner = null; } ! Statt Thread owner würde auch boolean busy reichen 

nsp3.25 Beispiel Implementierung einer Sperre (3.1.5  ):3.1.5 MONITOR Lock { private boolean lock; public void lock() { AWAIT !lock; lock = true; } public void unlock() { lock = false; } ! Wohlverhalten der Benutzer vorausgesetzt, d.h. alternierende x.lock(), x.unlock() !

6 Beispiel Implementierung einer Lese/Schreibsperre (3.1.5  ):3.1.5 MONITOR RWlock { private int readers; private int writers; public void Rlock() { AWAIT writers==0; readers++; } public void Wlock() { AWAIT readers==0 && writers==0; writers++; } public void Runlock() { readers--; } public void Wunlock() { writers--; } }

nsp3.27 Beispiel Puffer(3.1.2  ):3.1.2 public void send(M m) { AWAIT count<size; cell[rear] = m; count++; rear = (rear+1)%size; } public M recv() { AWAIT count>0; M m = cell[front]; count--; front = (front+1)%size; return m; }

nsp Wachen Deklarative Variante der Warteanweisung: Wartebedingung als Wache (guard) vor einem Operationsrumpf eines Monitors (gesperrt wird allerdings vor Auswertung der Wache) Vorteil:Voraussetzung (precondition) bewirkt Synchronisation Beispiel (nicht Java!): public void send(M m) WHEN count<size { cell[rear] = m; count++; rear = (rear+1)%size; }

9 ! Effiziente Übersetzung von AWAIT/WHEN ist schwierig ! 1. Nach jeder Zuweisung bei allen wartenden Prozessen die Wartebedingungen zu überprüfen ist undenkbar. 2. Daher die Forderung, daß die gemeinsamen Variablen in diesen Bedingungen nur Monitorvariable sein dürfen: damit kann sich die Überprüfung auf den Monitor, bei dem zugewiesen wird, beschränken (sofern – weitere Forderung! – es sich nicht um Verweisvariable handelt!). 3. Es genügt, die Wartebedingungen dann zu überprüfen, wenn der Monitor freigegeben wird, also beim Verlassen des Monitors oder bei einem Warten bei AWAIT. Das kann immer noch ineffizient sein.

Korrektheit Serialisierbarkeit:wie in 3.1.7, Def. 2, auch bei Blockaden3.1.7, Def. 2 Beispiel Puffer: SenderEmpfänger recv() AWAIT count>0; send('x') return; return m; produziert gleiches Ergebnis ("",'x') wie send recv

nsp3.211 Spezifikation und Verifikation fallen bei Wache leichter als bei Warteanweisung: { P } op(...); { Q }mit P = C & G & U, d.h. Bezug auf Implementierung : Nichterfüllung vonC(ondition) :löst Ausnahmemeldung aus G(uard) : löst Blockade aus U(ndef) :bewirkt undefiniertes Verhalten Programmiersprachliche Umsetzung – erfordert deklarative Auslösung von Ausnahmemeldungen: op(...) PRE C WHEN G {.....}

nsp3.212 Spezifikation bei Warteanweisung: { if(! C ) throw ; // op1 mit Effekt 1 (problematisch) AWAIT G ;......; // op2 mit Effekt 2 } (entsprechend 3,4,... ) Spezifikation:{ P } op(...); { Q } { P1 } op1 { Q1  ¬ G } { P2  G } op2 { Q2 } ! Bei mehrfachen AWAIT s nicht mehr praktikabel !

nsp Ereignissynchronisation Prozesse warten auf Ereignisse (events), die von anderen Prozessen ausgelöst werden. Mehrere Prozesse können auf ein Ereignis warten;  beim Eintreten des Ereignisses werden entweder alle Prozesse oder nur ein Prozess aufgeweckt;  das Ereignis „geht verloren“, wenn keiner wartet.

nsp Ereignisobjekte Systemklasse EVENT (auch Condition, Signal ), ausschließlich zur Benutzung in Monitoren (nicht Java!): class EVENT {... public void WAIT() {...} // releases monitor and // waits for this.SIGNAL() public void SIGNAL() {...} // awakes one process blocked // in this.WAIT(), if any public int WAITING() {...} // number of processes blocked // in this.WAIT() }

nsp3.215 Fairness bei Monitor-Freigabe: im Monitor blockierte Prozesse haben Vorrang vor eintrittswilligen Prozessen; bei SIGNAL : wer länger wartet hat Vorrang (FCFS).

nsp3.216 Beispiel Drucker (  ): wichtige Dokumentation! MONITOR Printer { private Thread owner = null; private final EVENT free = new EVENT(); // transition to owner==null public void request() { if(owner!=null) free.WAIT(); // { owner==null } owner = Thread.currentThread(); } public void release() { owner = null; // { owner==null } free.SIGNAL(); } }

nsp Signal-Varianten  signal-and-wait: aus WAIT aufgeweckter Prozess übernimmt Monitor, und aufweckender Prozess blockiert in SIGNAL (!). Begründung: Monitorübergabe ohne Zustandsänderung.  signal-and-continue: aus WAIT aufgeweckter Prozess übernimmt Monitor erst dann, wenn aufweckender Prozess ihn freigibt. Begründung: Effizienz.  signal-and-return: SIGNAL ist mit Verlassen des Monitors verbunden. Begründung: Vorteile von  und , begrenzter Nachteil.

nsp3.218 Beispiel Puffer (  ): private final EVENT notfull = new EVENT (); private final EVENT notempty = new EVENT (); public void send(Msg m) { if(count==size) notfull.WAIT(); cell[rear] = m; count++; rear = (rear+1)%size; notempty.SIGNAL(); } public Msg recv() { if(count==0) notempty.WAIT(); Msg m = cell[front]; count--; front = (front+1)%size; notfull.SIGNAL(); return m; }

nsp3.219 Beispiel Puffer (  ): private final EVENT notfull = new EVENT (); private final EVENT notempty = new EVENT (); public void send(Msg m) { if(count==size) notfull.WAIT(); cell[rear] = m; count++; rear = (rear+1)%size; notempty.SIGNAL(); } public Msg recv() { if(count==0) notempty.WAIT(); Msg m = cell[front]; count--; front = (front+1)%size; notfull.SIGNAL(); return m; } dies wäre nur mit  korrekt !

nsp3.220 Variante mit drei Ereignissen (korrekt für  ): private final EVENT urgent = new EVENT (); private final EVENT notfull = new EVENT (); private final EVENT notempty = new EVENT (); public void send(Msg m) { if(count==size) notfull.WAIT(); cell[rear] = m; if(m.isUrgent())urgent.SIGNAL(); else {count++; rear = (rear+1)%size; notempty.SIGNAL(); } } public Msg recvUrgent() { urgent.WAIT(); notfull.SIGNAL(); return cell[rear]; }

nsp3.221 Beispiel Zwei Drucker: MONITOR TwoPrinters { // "normal" and "special" // special includes normal capabilities private boolean normalbusy, specialbusy; private final EVENT printerfree = new EVENT (); private final EVENT specialfree = new EVENT (); public boolean request(boolean special) {.....} public void release(boolean special) {.....} }

nsp3.222 public boolean request(boolean special) { if(special){ if(specialbusy) specialfree.WAIT(); else specialbusy = true; else /* normal */ { if(normalbusy & specialbusy) printerfree.WAIT(); if(normalbusy) specialbusy = true; else {normalbusy = true; return false;} } return true; } public void release(boolean special) { if(special) if(specialfree.waiting()>0) specialfree.SIGNAL(); else {specialbusy = false; printerfree.SIGNAL(); else /* normal */ { normalbusy = false; printerfree.SIGNAL(); } } (ist korrekt für jede der 3 SIGNAL -Varianten)

nsp Ereignissynchronisation in Java mittels Operationen der Wurzelklasse Object – sofern der ausführende Thread das Objekt gesperrt hat (andernfalls IllegalMonitorStateException ): void wait() throws InterruptedException blockiert und gibt die Objektsperre frei void notify() weckt einen blockierten Thread auf (sofern vorhanden), gibt aber noch nicht die Sperre frei (vgl  )  void notifyAll() entsprechend für alle blockierten Threads

nsp3.224 Mit anderen Worten: Für jedes Objekt (Monitor) gibt es nur ein „Standard-Ereignis“ – das notify -Ereignis Fairness:keinerlei Garantien! Insbesondere konkurrieren nach notifyAll alle aufgeweckten Threads und die von außen hinzukommenden Threads um die Sperre. Warten mit Timeout: void wait(long msecs) wie wait, mit dem Zusatz, daß der blockierte Thread nach der angegebenen Zeit geweckt wird.

nsp3.225 Beispiel Betriebsmittel (Ressource, resource) wie z.B. Drucker (  ) oder Sperre: class Resource { private boolean busy; public synchronized void request() { if(busy) wait(); busy = true; } public synchronized void release() { busy = false; notify(); }

nsp3.226 Beispiel Betriebsmittel-Pool (z.B. Betriebsmittel = Speicherblock) hier: nur die Synchronisationsstruktur class Resources { private int available;... public synchronized void request(int claim) { while(claim > available) wait(); available -= claim; } public synchronized void release(int free) { available += free; notifyAll(); }

nsp3.227 Beispiel Puffer (  ): public synchronized void send(Msg m) { if(count==size) wait(); cell[rear] = m; count++; rear = (rear+1)%size; notify(); } public synchronized Msg recv() { if(count==0) wait(); Msg m = cell[front]; count--; front = (front+1)%size; notify(); return m; } ist nicht korrekt !

nsp Versuch: public synchronized void send(Msg m) { if(count==size) wait(); cell[rear] = m; count++; rear = (rear+1)%size; if(count==1) notify(); } public synchronized Msg recv() { if(count==0) wait(); Msg m = cell[front]; count--; front = (front+1)%size; if(count==size-1) notify(); return m; } ist nicht korrekt !

nsp Versuch: public synchronized void send(Msg m) { while(count==size) wait(); cell[rear] = m; count++; rear = (rear+1)%size; if(count==1) notify(); } public synchronized Msg recv() { while(count==0) wait(); Msg m = cell[front]; count--; front = (front+1)%size; if(count==size-1) notify(); return m; } ist nicht korrekt !

nsp Versuch – korrekt: public synchronized void send(Msg m) { while(count==size) wait(); cell[rear] = m; count++; rear = (rear+1)%size; if(count==1) notifyAll(); } public synchronized Msg recv() { while(count==0) wait(); Msg m = cell[front]; count--; front = (front+1)%size; if(count==size-1) notifyAll(); return m; }

nsp3.231 Beispiel Puffer-Variante (  ): private boolean urgent; public synchronized void send(Msg m) { while(count==size) wait(); cell[rear] = m; if(m.isUrgent()) urgent = true; else {count++; rear = (rear+1)%size; } notifyAll(); } public synchronized Msg recvUrgent() { while(!urgent) wait(); urgent = false; notifyAll(); return cell[rear]; } public synchronized Msg recv() { while(count==0 || urgent) wait();.....}

nsp3.232 Merke: Verzögerte Operation mit Ausnahmemeldung (nicht Java) op(...) PRE C WHEN G {.....} in Java realisieren durch das Idiom op(...) throws NotC { if(! C ) throw new notC (); while (! G ) wait();..... notifyAll(); } others(...).. notifyAll(); }

nsp3.233 Beispiel Betriebsmittel-Pool (z.B. Betriebsmittel = Speicherblock) hier: nur die Synchronisationsstruktur MONITOR Resources { // this is NOT JAVA private final int max =...; private int available = max; public void request(int claim) PRE claim <= max WHEN claim <= available { available -= claim; } public void release(int free) { available += free; } }

nsp3.234 Beispiel Betriebsmittel-Pool (z.B. Betriebsmittel = Speicherblock) hier: nur die Synchronisationsstruktur class Resources { // this IS JAVA private final int max =...; private int available = max; public synchronized void request(int claim)... { if (claim > max) throw new... while(claim > available) wait(); available -= claim; } public synchronized void release(int free) { available += free; notifyAll(); } }

nsp3.235 Unabhängige Ereignisse (d.h. nicht an Daten gebunden): Object x = new Object(); „Ereignis x“ synchronized(x){x.wait();} „warte auf x“ synchronized(x){x.notifyAll();} „x tritt ein“ Achtung: Ereignis „geht verloren“, wenn keiner wartet Achtung, Achtung:kein Ersatz für Events gemäß ! synchronized void op(){..... synchronized(x){x.wait();}... } führt zu Verklemmung !

nsp Nachrüsten von Synchronisation am Beispiel Schlange mit exceptions  Puffer ohne exceptions class LinearQueue implements Queue { public final int size; protected int count; public void append(Message m) PRE count < size {.....} public Message remove() PRE count > 0 {.....} public int length() {.....} } (vgl )3.1.3

nsp mit Vererbung: umdefinierte Operationen (ohne exceptions!) MONITOR Buffer extends LinearQueue { public Buffer(int size) {super(size);} public void append(Message m) WHEN count < size {super.append(m);} public Message remove() WHEN count > 0 {return super.remove();} public int length() {return super.length();} } Achtung! Bei Einführung anderer Namen – z.B. send statt append – würden die unsynchronisierten Operationen sichtbar bleiben!

nsp mit Delegation: (ebenfalls ohne exceptions) MONITOR Buffer implements Queue { private final Queue q; public Buffer(int size) { q = new LinearQueue (size); public void append(Message m) WHEN q.length() < q.size {q.append(m);} public Message remove() WHEN q.length() > 0 {return q.remove();} public int length() {return q.length();} }