Übung „Nichtsequentielle Programmierung“ Sommer 2009 Prof. Dr. Marcel Kyas Blatt 6 Aufgabe 25 (10 Punkte) Zeigen Sie, dass man allgemeine Semaphore mit binären Semaphoren simulieren kann. Das bedeutet, dass jedes Programm, das allgemeine Semaphore benutzt, in eines umgeschrieben werden kann, das nur binäre Semaphore benutzt. Aufgabe 26 (10 Punkte) Betrachten Sie die Implementierung eines bounded buffer in Abbildung 1. Schreiben Sie eine Version, die nur mit binären Semaphoren auskommt. Sie werden vielleicht weitere Semaphore und weitere Variablen brauchen. Benutzen Sie ruhig Ihr Ergebnis aus Aufgabe 25. Aufgabe 27 (Programmieraufgabe) Entwickeln Sie einen bounded buffer, der von mehreren Produzenten und Konsumenten gemeinsam benutzt werden kann. Modifizieren Sie den Algorithmus aus Abbildung 1 dergestalt, das mehrere Werte zur gleichen Zeit angefügt werden können bzw mehrere Werte gleichzeitig entnommen werden können. Jedes Anfügen muss das neue Datum in ein anderes, leeres Feld anfügen. Jedes Holen muss ebenfalls aus einem anderen Feld holen. Aufgabe 28 (Programmieraufgabe) Dieses Problem beschäftigt sich mit atomic broadcast. Nehmen Sie an, es gibt einen Produzenten- und n Konsumentenprozesse, die einen gemeinsamen Puffer benutzen. Der Produzent legt eine Nachricht in diesem Puffer ab, und die 1 Object[] buf = new Object[n]; int front = 0, rear = 0; Semaphore full = new Semaphore(0), empty = new Semaphore(n); // Invariant: buf.length−2 <= empty.availablePermits() + full.availablePermits() <= buf.length public void produce() { Object data; for (;;) { // produce data empty.acquireUninterruptible(); buf[rear] = data; rear = (rear + 1) % buf.length; full.release(); }} public void consume() { Object data; for (;;) { full.acquireUninterruptible(); data = buf[front]; front = (front + 1) % buf.length; empty.release(); // use data for processing }} Abbildung 1: Bounded buffer Konsumenten holen diese Nachricht ab. Jede Nachricht, die vom Produzenten im Puffer abgelegt wird, muss von allen n Konsumenten abgeholt werden, bevor der Produzent die nächste Nachricht ablegen darf. 1. Entwickeln Sie eine Lösung für dieses Problem. Benutzen Sie Semaphore zur Lösung. 2. Nehmen Sie nun an, dass der Puffer b Plätze hat. Der Produzent kann Nachrichten nur in einen freien Platz ablegen. Jede abgelegte Nachricht muss von allen n Konsumenten abgeholt werden, bevor der Platz wieder benutzt werden kann. Weiterhin muss jeder Konsument jede Nachricht empfangen. Es ist aber nicht notwendig, dass ein Konsumenten die Nachrichten zur gleichen Zeit wie andere Konsumenten empfängt. Zum Beispiel kann ein Konsument bis zu b Nachrichten empfangen, wenn ein zweiter Konsument langsam ist. Erweitern Sie Ihre Antwort zu 1. um dieses allgemeinere Problem zu lösen. 2 Aufgabe 29 (10 Punkte) Betrachten Sie die Lösung des readers-writers problem in Abbildung 2 (dies ist die gleiche Lösung aus der Vorlesung). Ist diese Lösung fair, d.h., ist es immer garantiert, dass jeder Leser, der die Datenbank lesen möchte, dies auch schließlich tut? Ist es immer garantiert, dass jeder Schreiber, der auf die Datenbank schreiben möchte, diese immer tun wird? Begründen Sie Ihre Antwort. Semaphore rw = new Semaphore(1), rd = new Semaphore(1); int nr = 0; // Invariant (nw = 0 ∨ nr = 0) ∧ (nw ≤ 1) public void reader() { for (;;) { // do something rd.acquireUninterruptible(); if (++nr == 1) rw.acquireUninterruptible(); rd.release(); // read the data base rd.acquireUninterruptible(); if (−−nr == 0) rw.release(); rd.release(); } } public void writer() { for (;;) { // do something rw.acquireUninterruptible(); h nw = nw + 1 i; // read and write the data base h nw = nw − 1 i; rw.release(); }} Abbildung 2: Readers Writers Aufgabe 30 (20 Punkte) Betrachten Sie die nachfolgende Lösung des readers-writers problem. Erklären Sie die Rolle jeder einzelnen Semaphore. Entwickeln sie Zusicherungen, die anzeigen, was an kritischen Stellen gilt. Erklären Sie insbesondere, warum Schreiber exklusiven Zugriff auf die Datenbank haben, d.h, wann immer ein Schreiber in seiner kritischen Sektion ist, gibt es keinen anderen Schreiber und keinen anderen Leser, der in seiner kritischen Sektion ist. 3 Erklären Sie, warum diese Lösung nicht fair ist. Insbesondere gibt diese Lösung den Schreibern den Vorzug. Warum? Bemerkung: Hier ist kein Beweis gefordert, auch wenn der Beweis die Korrektheit ihrer Zusicherungen zeigt. Abgabe Die Lösungen der Aufgaben 25, 26, 29 und 30 sind bis zum 2. Juni, 12:00 Uhr, in den Briefkasten Ihres Tutors neben Raum 137 einzuwerfen. Die Lösungen der Programmieraufgaben 27 und 28 sind bis zum 2. Juni dem Tutor zuzuschicken. 4 Semaphore m1 = new Semaphore(1), m2 = new Semaphore(1), m3 = new Semaphore(1); Semaphore read = new Semaphore(1), write = new Semaphore(1); int nr = 0, nw = 0; // Invariant (nw = 0 ∨ nr = 0) ∧ (nw ≤ 1) public void reader() { for (;;) { // do something m3.acquireUninterruptible(); read.acquireUninterruptible(); m1.acquireUninterruptible(); nr = nr + 1; if (nr == 1) write.acquireUninterruptible(); m1.release() read.release(); m3.release(); // read the data base m1.acquireUninterruptible(); nr = nr − 1; if (nr == 0) write.release(); m1.release(); } } public void writer() { for (;;) { // do something m2.acquireUninterruptible(); nw = nw + 1 if (nw == 1) read.acquireUninterruptible(); m2.release() write.acquireUninterruptible(); // read and write the data base write.release(); m2..acquireUninterruptible(); nw = nw − 1; if (nw == 0) read.release(); m2.release(); } } Abbildung 3: Alternativer Readers-Writers 5