Nebenläufige Programmierung in Java



Ähnliche Dokumente
Systeme 1. Kapitel 6. Nebenläufigkeit und wechselseitiger Ausschluss

Java: Vererbung. Teil 3: super()

Innere Klassen in Java

Objektorientierte Programmierung. Kapitel 12: Interfaces

Programmieren in Java

Java Kurs für Anfänger Einheit 4 Klassen und Objekte

Prof. Dr. Uwe Schmidt. 21. August Aufgaben zur Klausur Objektorientierte Programmierung im SS 2007 (IA 252)

Große Übung Praktische Informatik 1

5. Abstrakte Klassen. Beispiel (3) Abstrakte Klasse. Beispiel (2) Angenommen, wir wollen die folgende Klassenhierarchie implementieren:

Einführung in die Java- Programmierung

Java Virtual Machine (JVM) Bytecode

Objektorientierte Programmierung

Synchronisation in Java. Invisible Web

Programmierkurs Java

Java Kurs für Anfänger Einheit 5 Methoden

5. Abstrakte Klassen

Algorithmen und Datenstrukturen

Verhindert, dass eine Methode überschrieben wird. public final int holekontostand() {...} public final class Girokonto extends Konto {...

Objektorientierte Programmierung für Anfänger am Beispiel PHP

Softwarelösungen: Versuch 4

Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung: Lösungsvorschlag

Grundlagen von Python

Einführung in die Java- Programmierung

Klausur zur Einführung in die objektorientierte Programmierung mit Java

II. Grundlagen der Programmierung. 9. Datenstrukturen. Daten zusammenfassen. In Java (Forts.): In Java:

SEP 114. Design by Contract

Verteilte Systeme CS5001

Zählen von Objekten einer bestimmten Klasse

Prinzipien Objektorientierter Programmierung

Einführung in die Programmierung

Folge 19 - Bäume Binärbäume - Allgemeines. Grundlagen: Ulrich Helmich: Informatik 2 mit BlueJ - Ein Kurs für die Stufe 12

C# im Vergleich zu Java

Prozeß P1 Prozeß P2. Zur Synchronisation stehen den beiden Prozessen binäre Semaphore und die beiden Funktionen

Software Engineering Klassendiagramme Assoziationen

Kapitel 6. Vererbung

Applet Firewall und Freigabe der Objekte

Kapitel 6. Vererbung

Übung: Verwendung von Java-Threads

Software Engineering Interaktionsdiagramme

Vorkurs C++ Programmierung

Einführung in Java. PING e.v. Weiterbildung Andreas Rossbacher 24. März 2005

Binäre Bäume. 1. Allgemeines. 2. Funktionsweise. 2.1 Eintragen

Kapitel 4. Monitore und wechselseitiger Ausschluss

Der Aufruf von DM_in_Euro 1.40 sollte die Ausgabe 1.40 DM = Euro ergeben.

Typumwandlungen bei Referenztypen

2.2 Prozesse in Java

Monitore. Klicken bearbeiten

1 Vom Problem zum Programm

Kapitel 6. Vererbung

Datenbank-Verschlüsselung mit DbDefence und Webanwendungen.

Fachgebiet Informationssysteme Prof. Dr.-Ing. N. Fuhr. Programmierung Prof. Dr.-Ing. Nobert Fuhr. Übungsblatt Nr. 6

Technische Universität München SS 2006 Fakultät für Informatik 12. Oktober 2006 Prof. Dr. A. Knoll. Aufgabe 1 Transferfragen (Lösungsvorschlag)

Was meinen die Leute eigentlich mit: Grexit?

Software Engineering Klassendiagramme Einführung

Institut für Programmierung und Reaktive Systeme 25. August Programmier-Labor Übungsblatt. int binarysearch(int[] a, int x),

Grundlagen der Theoretischen Informatik, SoSe 2008

Musterlösungen zur Klausur Informatik 3

Professionelle Seminare im Bereich MS-Office

BEISPIELKLAUSUR Softwareentwicklung:

Session Beans & Servlet Integration. Ralf Gitzel ralf_gitzel@hotmail.de

Überblick. Lineares Suchen

Klassenentwurf. Wie schreiben wir Klassen, die leicht zu verstehen, wartbar und wiederverwendbar sind? Objektorientierte Programmierung mit Java

Einführung in die objektorientierte Programmierung mit Java. Klausur am 19. Oktober 2005

Java Einführung Abstrakte Klassen und Interfaces

2A Basistechniken: Weitere Aufgaben

Objektorientierte Programmierung

Das erste Programm soll einen Text zum Bildschirm schicken. Es kann mit jedem beliebigen Texteditor erstellt werden.

1. Man schreibe die folgenden Aussagen jeweils in einen normalen Satz um. Zum Beispiel kann man die Aussage:

Lineargleichungssysteme: Additions-/ Subtraktionsverfahren

Updatehinweise für die Version forma 5.5.5

Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung: Lösungsvorschlag

Sichtbarkeit & statische Methoden. Einsatz von Sichtbarkeit Einsatz statischer Methoden programmatische Realisierung 2 Beispielaufgaben

Client-Server-Beziehungen

Print2CAD 2017, 8th Generation. Netzwerkversionen

Übersicht. Schleifen. Schleifeninvarianten. Referenztypen, Wrapperklassen und API. 9. November 2009 CoMa I WS 08/09 1/15

Javadoc. Programmiermethodik. Eva Zangerle Universität Innsbruck

5 DATEN Variablen. Variablen können beliebige Werte zugewiesen und im Gegensatz zu

Programmiervorkurs SS 2011 Technische Universität Darmstadt Jan Hendrik Burdinski, Felix Kerger

Einfache Arrays. Annabelle Klarl. Einführung in die Informatik Programmierung und Softwareentwicklung

Übung Grundlagen der Programmierung. Übung 03: Schleifen. Testplan Testergebnisse

Softwaretechnologie -Wintersemester 2013/ Dr. Günter Kniesel

Delegatesund Ereignisse

Einführung in PHP. (mit Aufgaben)

Lösungsvorschläge. zu den Aufgaben im Kapitel 4

Design by Contract with JML

3 Objektorientierte Konzepte in Java

Rekursion. Annabelle Klarl. Einführung in die Informatik Programmierung und Softwareentwicklung

Primzahlen und RSA-Verschlüsselung

C++ Grundlagen. ++ bedeutet Erweiterung zum Ansi C Standard. Hier wird eine Funktion eingeleitet

Übung 8: Semaphore in Java (eigene Implementierung)

Was ist Sozial-Raum-Orientierung?

Praktikum zu Einführung in die Informatik für LogWiIngs und WiMas Wintersemester 2015/16. Vorbereitende Aufgaben

Stellen Sie bitte den Cursor in die Spalte B2 und rufen die Funktion Sverweis auf. Es öffnet sich folgendes Dialogfenster

Programmieren. 10. Tutorium 4./ 5. Übungsblatt Referenzen

5. Tutorium zu Programmieren

Konfiguration des ewon GSM Modems Kurzbeschreibung zum Aufbau einer GSM Verbindung

Fachdidaktik der Informatik Jörg Depner, Kathrin Gaißer

Statuten in leichter Sprache

Grundbegriffe der Informatik

Probeklausur Softwareengineering SS 15

Transkript:

Informatik IV 37-004 SS 2002 Thomas Gross Diese Slides kommen ohne Gewähr. 9-1 Thomas Gross 1997-2000 Nebenläufige Programmierung in Java Threads und deren Zustände Speichermodell Einfache Synchronisation 9-2 Thomas Gross 1997-2000 Page 1

Konzept Threads Threads stehen in Java für das was wir Prozess in unseren bisherigen Überlegungen zur Nebenläufigkeit genannthaben Wir brauchen ein Modell, um die Ausführungen von Programmen in einem parallelen System zu beschreiben. Wir wollen uns nicht genau um die Anzahl der CPUs kümmern Unsere Ergebnisse sollen für alle möglichen Systeme gelten, nicht nur für ein bestimmtes Wir nennen das Konzept der Ausführung einer Folge von Operationen einen Thread. Ein Thread weiss, welche Operation als nächste auszuführen ist. 9-3 Thomas Gross 1997-2000 Threads Ein Thread braucht einen Arbeitsspeicher (Adressraum), um Daten und Zwischenergebnisse zu speichern. Adressraum des Threads: alle Objekte, die via Verweise erreichbar sind. Ein Adressraum kann mehreren Threads dienen. Java: Lokale Variable und Methodenparameter sind nur für den aufrufenden Thread sichtbar (Laufzeitstack) Klassenvariable oder mittels new erzeugte Objekte (Heap) sind im Prinzip für alle Threads sichtbar 9-4 Thomas Gross 1997-2000 Page 2

Speichermodell Ähnlich shared memory Thread 1 + lokaler Speicher Thread 2 + lokaler Speicher Thread 3 + lokaler Speicher Gemeinsamer Speicher Bemerkung: Threads werden vom Scheduler auf tatsächlich vorhandene CPUs abgebildet. 9-5 Thomas Gross 1997-2000 Threads und Prozessoren Ein Thread kann von jeder CPU im System ausgeführt werden Ein Thread kann nach jeder Operation unterbrochen werden Er kann auf einer anderen CPU weiter ausgeführt werden Er kann für eine Zeit aussetzen Wir können mit diesem Modell auch die Ausführung mehrerer Threads auf einer CPU beschreiben 9-6 Thomas Gross 1997-2000 Page 3

Quasi-Parallel Mehrere Threads werden auf einer CPU ausgeführt. Wir wissen nicht, wann Unterbrechungen stattfinden ( nach jeder Operation möglich ) Wir sagen, die Threads werden quasi -parallel ausgeführt Unsere Programme sollen für alle möglichen Ausführungen korrekt sein -> Konzeptionell kein Unterschied zur echten Parallelität (n CPUs) -> Allgemein: Nebenläufige Java Programme 9-7 Thomas Gross 1997-2000 Threads Threads in Java eingebaut. Jedes Java Programm wird durch eine Anzahl von Threads ausgeführt. Garbage Collector ist eigener Thread AWT Thread Zusätzlich können vom Benutzer Threads definiert, gestartet, und gemanaged werden. 9-8 Thomas Gross 1997-2000 Page 4

Threads und Prozessoren Die genauen Regeln wann ein Thread eine CPU bekommt (und wann sie wieder abgegeben wird) hängen von der Implementation des Systemes ab. Insbesondere können wir nicht Fairness voraussetzen. Programm sollte sich nicht auf Fairness verlassen» Trotzdem muss es unsere Anforderungen erfüllen Unterschiedliche Ergebnisse auf verschiedenen Platformen (oder Versionen) möglich! 9-9 Thomas Gross 1997-2000 Threads sind Objekte Alle Aussagen für Object gelten auch für Threads. Thread t = new Thread(); Threads können verschiedene Zustände annehmen: Instanziert (der Thread existiert)» d.h. es wurde der Konstruktor ausgeführt. Ausführbar (der Thread kann die CPU besetzen, so dass Instruktionen ausgeführt werden können) -- evtl. hat der Thread sogar die CPU. Suspended (der Thread kann z.zt. nicht ausgeführt werden, z.b. weil er wartet) Dead (der Thread ist nicht mehr aktiv, aber die Felder können noch inspiziert [und verändert] werden)» Threads sind Objects.» Es gibt auch Konstruktoren von Thread, die einen anderen Thread als Parameter akzeptieren De-alloziert (dem Garbage Collector überlassen) 9-10 Thomas Gross 1997-2000 Page 5

Thread Management Die start() Methode macht einen Thread ausführbar Wann der Thread ausgeführt wird, hängt vom System (u.a. den anderen Threads) ab. Siehe Bemerkung über Zeitpunkt des Besitzes der CPU Beispiel Thread t = new Thread(); t.start(); Die Methode start() verwaltet nur den Thread, sofortiger Rückkehr (nachdem die Buchhaltung up-to-date ist). Offene Frage: Was führt der Thread aus? 9-11 Thomas Gross 1997-2000 Zustände new this.yield instanziert this.start ausführbar this.sleep, other.join, obj.wait, block on synchronized ende run methode this.interrupt, obj.notify[all], enter synchronized suspended de-alloziert dead Keine Referenz auf das Thread Objekt existiert mehr this ~ aktueller Thread other ~ anderer Thread obj ~ irgendein Objekt Zustandsübergänge nicht vollständig 9-12 Thomas Gross 1997-2000 Page 6

Prioritäten Cooperative Threads: Alle Threads haben gleiche Priorität Thread gibt freiwillig Ausführungsrecht ab (Methoden yield() oder sleep()) Premptive Threads: Threads können unterschiedliche Prioritäten haben (setpriority(), getpriority()) Scheduler unterbricht Threads (mit niedriger Priorität, regelmässig) -> nicht genau festgelegt in der Java Spezifikation -> Programmierer sollte sich niemals auf Scheduler bzw. zeitliches Verhalten verlassen 9-13 Thomas Gross 1997-2000 Verhalten eines Threads Jede Instanz der Klasse Thread führt eine vorgegebene Methode aus Signatur ist festgelegt Name: run() run() ist eine parameter-lose Methode, die ausgeführt wird, nachdem der Thread aktiviert wurde (mittels start()). Expliziter Aufruf von run() nur wenn wir auf den Return warten wollen (oder müssen). Sofortiger Return von Methode start() Strategie Muster (abstrakte Strategieklasse ist Runnable) 9-14 Thomas Gross 1997-2000 Page 7

Strategie: Thread Aktivität Threads implementieren das Interface Runnable. interface Runnable { void run(); Festlegen des Verhaltens durch Erweiterung der Thread Klasse (Neu)Definition vonrun() class MyThread extends Thread { public void run() { // actual code 9-15 Thomas Gross 1997-2000 class PingPong extends Thread { String word; int delay; PingPong (String msg, int delaytime) { word = msg; delay = delaytime; public void run () { try { for (; ; ) { System.out.println(word + " " ); sleep (delay); catch (InterruptedException e) { return; 9-16 Thomas Gross 1997-2000 Page 8

(2.Teil) public class TrivialApplication { public static void main(string args[]) { new PingPong("foo", 5000).start(); new PingPong("bar", 2500).start(); System.out.println( "Done" ); Output: Done foo bar bar foo bar foo bar bar bar 9-17 Thomas Gross 1997-2000 Unteilbare Operationen Nochmals ein Blick auf das Speichermodell. Sind Speicherzugriffe atomar? Wann sieht ein Thread Veränderungen die ein anderer Thread durchführte? Sehen alle Threads alle Speicherzugriffe in der gleichen Reihenfolge? Als Benutzer einer Programmiersprache sehen wir im Language Reference Manual nach... wenn wir Glück haben gibt es da eine Auskunft! In Java sind diese Aspekte relativ genau festgelegt...... andere Programmiersprachen überlassen die Entscheidung dem Entwickler des Compilers/Laufzeitsystems... oder denken garnicht an diesen Problembereich 9-18 Thomas Gross 1997-2000 Page 9

Java: Speicherzugriffe Nebenläufiger Zugriff auf Basistypen (ausser double und long) (1) Kein Korrumpieren von Daten: Schreib- bzw. Lesevorgang nicht unterbrechbar (atomar) (2) Keine Garantie bzgl. der Ausführungsreihenfolge für Zugriffe auf unterschiedliche Variable innerhalb eines Threads. (3) Keine Garantie bzgl. der Reihenfolge, in der Schreibzugriffe auf gemeinsame Variable für andere Threads sichtbar werden Java: Fürdouble und long, Arrays und Referenztypen gilt (1) nicht! 9-19 Thomas Gross 1997-2000 Konsistenz: Speicherbild Problem: Alle Threads sollen ein konsistentes (= übereinstimmendes) Speicherbild haben. Nicht selbstverständlich: Vorhandensein von threadlokalen Caches / Registern, Umordnen von Instruktionen durch den Compiler Variablen könnenvolatile deklariert werden: Dann hat man stärkere Garantien für Atomizität, Sichtbarkeit und Reihenfolge als auf dem letzten Slide erklärt. volatile hilft nicht um Speicherbild von ganzen Arrays oder Objekten konsistent zu halten Also: alle Variablen, die von mehreren Threads gelesen oder geschrieben werden, sollten volatile sein. 9-20 Thomas Gross 1997-2000 Page 10

Konsistenz: Speicherzustand Problem: Gemeinsamer Speicher kann von mehreren Threads verändert werden. Selbst bei konsistentem Speicherbild kann es zu inkonsistentem Speicherzustand kommen: Wir müssen aufpassen, dass die Änderungen in der richtigen Reihenfolge bzw. nach gewissen Regeln passieren Explizite Kontrolle der Abfolge von Operationen (= Kontrollfluss) unterschiedlicher Threads: Synchronisation Beispiel: Lost-Update Problem 9-21 Thomas Gross 1997-2000 Lost update class Account { volatile int balance = 1; void transaction(int i) { balance = balance + i; // not atomic! int getbalance() { return balance; Problem falls mehrere Threads auf der gleichen Instanz von Account die Methode transaction ausführen! 9-22 Thomas Gross 1997-2000 Page 11

int c1 = 1; // global int c2 = 1; int turn; Dekker s Lösung Prozess 1: // non-critical section c1 = 0; while (!(c2 == 1)){ if (turn == 2) { c1 = 1; while (! (turn==1)){ c1 = 0; // critical section c1 = 1; turn = 2; Prozess 2: // non-critical section c2 = 0; while (!(c1 == 1)) { if (turn == 1) { c2 = 1; while (! (turn==2)){ c2 = 0; // critical section c2 = 1; turn = 1; 9-23 Thomas Gross 1997-2000 class Dekker { volatile int c1 = 1; volatile int c2 = 1; volatile int turn; class Thread1 extends Thread { Dekker d_; Thread1 (Dekker d) {d_ = d; Dekker slösung class Thread2 extends Thread { Dekker d_; Thread2 (Dekker d) {d_ = d; public void run() { public void run() { // non-critical section // non-critical section d_.c1 = 0; d_.c2 = 0; while (!(d_.c2 == 1)){ while (!(d_.c1 == 1)) { if (d_.turn == 2) { if (d_.turn == 1) { d_.c1 = 1; d_.c2 = 1; while (!(d_.turn==1)){ while (! (d_.turn==2)){ d_.c1 = 0; d_.c2 = 0; // critical section // critical section d_.c1 = 1; d_.c2 = 1; d_.turn = 2; d_.turn = 1; 9-24 Thomas Gross 1997-2000 Page 12

Dekker s Lösung class Test { public static void main(string[] args) { Dekker d = new Dekker(); new Thread1(d).start(); new Thread2(d).start(); System.out.println("Done."); 9-25 Thomas Gross 1997-2000 Bakery Algorithmus Idee: jeder Kunde nimmt ein Ticket mit einer Zahl Wenn ein Verkäufer frei wird, wird der Kunde mit dem Ticket mit der kleinsten Nummer bedient Vorteil: es gibt keine Variable, die von allen Prozessen gelesen und geschrieben werden muss. 9-26 Thomas Gross 1997-2000 Page 13

int c1 = 0; // global int c2 = 0; Bakery - 2 Prozesse Prozess 1: // non-critical section c1 = 1; c1 = c2 + 1; while (!( (c2 == 0) (c1 <= c2)) ){ // critical section c1 = 0; Prozess 2: // non-critical section c2 = 1; c2 = c1 + 1; while (!( (c1 == 0) (c2 < c1)) ){ // critical section c2 = 0; 9-27 Thomas Gross 1997-2000 Bakery Algorithmus Garantiert gegenseitigen Ausschluss Verhindert Deadlock 9-28 Thomas Gross 1997-2000 Page 14

Bakery - N Prozesse int [] c = new int [N+1]; // c[0] not used! init to 0 int [] n = new int [N+1]; // n[0] not used! init to 0 // max(n) : maximum number in n Prozess i: // non-critical section c[i] = 1; n[i] = 1 + max(n); c[i] = 0; for (int ti=1; ti<n+1; ti++) { if (ti!= i) { while (!(c[ti] == 0)){ while (! ((n[ti] == 0) (n[i] < n[ti]) ((n[i] == n[ti]) && (i < ti)) )) { // critical section n[i] = 0; 9-29 Thomas Gross 1997-2000 Andere Modelle Trotzdem sind diese Lösungen nicht besonders elegant Wir wollen nicht unseren Code mit diesen Protokoll Operationen durchsetzen Ein Prozess der auf Zugang zu seiner critical section wartet verbraucht (Prozessor) Ressourcen 9-30 Thomas Gross 1997-2000 Page 15

Semaphore Vereinfachung des Protokolls Operationen die einem Prozess es erlauben, die critical section auszuführen Idee: EntryTest() --» Erfolg (d.h. Return): Critical Section kann ausgeführt werden» Noch kein Return: Warten ExitNotification() -- ein Prozess verlässt die Critical Section» Andere Prozesse duerfen weiter machen 9-31 Thomas Gross 1997-2000 Semaphore Idee: diese EntryTest() Methoden werden auf Objekte angewendet die einen Integer Wert W haben Wert immer >= 0 Wenn Wert W > 0 dann: EntryTest () reduziert W um 1 (W = W - 1) und lässt den Prozess weiter» Sonst muss der Prozess warten ExitTest(): wenn andere Prozesse warten, dann wird einer aktiviert, sonst wird W um 1 erhöht Diese Objekte nennen wir Semaphore Sei S ein Semaphor. S.p() -- EntryTest S.v() -- ExitNotification 9-32 Thomas Gross 1997-2000 Page 16

P() und V() Operationen P() und V() werden atomar ausgeführt Ein Semaphor kann mit einem beliebigen (nichtnegativem) Wert initialisiert werden. 9-33 Thomas Gross 1997-2000 Beispiel: Gegenseitiger Ausschluss Semaphore sema = new Semaphore(); sema.value = 1; // init Prozess 1: // non-critical section sema.p(); // critical section sema.v(); Prozess 2: // non-critical section sema.p(); // critical section sema.v(); 9-34 Thomas Gross 1997-2000 Page 17

Invarianten Nach unserer Definition gilt immer für einen Semaphor sema: sema.value >= 0 sema.value = sema.init_value + #Vs - #Ps Nur ein Prozess, der erfolgreich sema.p() durchgeführt hat, kann eine exitnotification Operation (sema.v()) ausführen. 9-35 Thomas Gross 1997-2000 Verhalten bei V() Nachdem ein Prozess sema.v() ausgeführt hat, wird ein anderer Prozess, der auf sema wartete, aktiviert. Frage: wenn es mehr als einen gibt, welcher Prozess wird ausgeführt? Antwort: Hängt ab von der Art/Variation des Semaphors. 9-36 Thomas Gross 1997-2000 Page 18

Producer-Consumer Grundmuster verschiedener Anwendungen Producer P --> Consumer C Geschwindigkeit von P und C zeitweilig unterschiedlich Buffer zwischen P und C Zuerst: unendlicher Buffer 9-37 Thomas Gross 1997-2000 int [] b; int in, out; Unendlicher Buffer Prozess P: int j; produce(j); b[in] = j; in++; Prozess C: int j; < await (in > out) j = b[out]; out ++; > consume(j); <await (B) S;> kann implementiert werden durch -- Lesen eines Zaehlers (mit Dekker s Lösung) -- Semaphore 9-38 Thomas Gross 1997-2000 Page 19

int [] b; int in, out; Semaphore access = new Semaphore(); access.value = 0; Synchronization Prozess P: int j; produce(j); b[in] = j; in++; access.v(); Prozess C: int j; access.p(); j = b[out]; out ++; consume(j); 9-39 Thomas Gross 1997-2000 int [] b = new int[n]; int in, out; Semaphore access = new Semaphore(); access.value = 0; Semaphore space = new Semaphore(); space.value = N; Endlicher Buffer Prozess P: int j; produce(j); space.p(); b[in] = j; in = mod(in+1,n); access.v(); Prozess C: int j; access.p(); j = b[out]; out = mod(out+1,n); space.v(); consume(j); 9-40 Thomas Gross 1997-2000 Page 20

Mehrere Buffer Wenn es mehrere Buffer gibt, dann kann es auf subtile Weise ein Deadlock geben. 9-41 Thomas Gross 1997-2000 int [] b1 = new int[n]; int [] b2 = new int[n]; int in, out; Semaphore access = new Semaphore(); access.value = 0; Semaphore space = new Semaphore(); space.value = N; Mehrere Buffer (2) Prozess P: int j1,j2; // produce(j1, j2); space.p(); b1[in] = j1; b2[in] = j2; in = mod(in+1,n); access.v(); Prozess C: int j1, j2; access.p(); j1 = b1[out]; j2 = b2[out]; out = mod(out+1,n); space.v(); // consume(j1, j2); 9-42 Thomas Gross 1997-2000 Page 21

int [] b1 = new int[n1]; int [] b2 = new int[n2]; int in1, in2, out1, out2; Semaphore access1, access2, space1, space2; // create semaphores access1.value = 0; access2.value = 0; space1.value = N1; space2.value = N2; Prozess P: int j1,j2; // K1 elements in b1 for (int k=0; k<k1; k++) { produce(j1); space1.p(); b1[in] = j1; in1 = mod(in1 + 1,N1); access1.v(); Mehrere Buffer (3A) Prozess C: int j1, j2; // K2 elements from b2 for (int k=0; k<k2; k++) access2.p(); j2 = b2[out2]; out2 = mod(out2+1,n); space2.v(); consume(j2); 9-43 Thomas Gross 1997-2000 Mehrere Buffer (3B) // Fortsetzung von Buffer (3A) // K2 elements in b2 for (int k=0; k<k2; k++) { produce(j2); space2.p(); b2[in2] = j2; in2 = mod(in2 + 1,N2); access2.v(); // end of while // // K1 elements from b1 for (int k=0; k<k1; k++) { access1.p(); j1 = b1[out1]; out1 = mod(out1+1,n); space1.v(); consume(j1); // end of while Beispiele N1 = 100, N2 = 100, K1 = 10, K2 = 10 N1 = 100, N2 = 100, K1 = 101, K2 = 10 Programmieren mit Semaphoren trickreich. Es kann schwer sein, die Logik der Synchronization zu erkennen. 9-44 Thomas Gross 1997-2000 Page 22

Fortsetzung 9-45 Thomas Gross 1997-2000 Binäre Semaphore Wenn der Semaphore nur die Werte 0 oder 1 annehmen kann, dann sprechen wir von einem binären Semaphor. Interessant weil oft leicht zu realisieren. 9-46 Thomas Gross 1997-2000 Page 23

Weitere Informationen Es gibt eine Reihe von Büchern über die Themen dieser Vorlesung. M. Ben-Ari Principles of Concurrent and Distributed Programming, Prentice Hall, 1990 (ISBN: 0-13-711821) G. Andrews Foundations of Multhithreaded, Parallel, Distributed Programming, Addison Wesley, 2000 (ISBN: 0-201-35752-6) 9-47 Thomas Gross 1997-2000 Page 24