Lehrstuhl für Praktische Informatik III Prof. Dr. Guido Moerkotte Email: [email protected] Norman May B6, 29, Raum C0.05 68131 Mannheim Telefon: (0621) 181–2517 Email: [email protected] Transaktionssysteme Sommersemester 2005 1. Übungsblatt 27. April 2005 Aufgabe 1 Schreiben Sie ein Programm, das eine partielle Ordnung (einen gerichteten Graph) topologisch sortiert. Welche Komplexität hat Ihr Programm? Lösung package infra; import java.util.HashSet; import java.util. Iterator ; import java.util.Set; /∗∗ ∗ Sort a directed acyclic graph topologically . ∗/ public class TopologicalSort { /∗∗ the graqph to sort topologically ∗/ private Set theGraph; /∗∗ holds the toplogically ordered nodes ∗/ private Node[] theResult; /∗∗ the write position ∗/ private int theWritePos; /∗∗ the set of inserted nodes ∗/ private Set theDoneNodes; public TopologicalSort(Set graph) { theGraph = graph; theWritePos = theGraph.size(); theResult = new Node[theWritePos]; theDoneNodes = new HashSet(); } /∗∗ do sort the graph, based on the incident edges ∗/ public Node[] sort() { 1 if (theWritePos == 0 && theDoneNodes.size() == theGraph.size()) { // already sorted before return theResult; } for ( Iterator iter = theGraph.iterator() ; iter .hasNext(); ) { insert ((Node) iter.next()) ; } return theResult; } /∗∗ insert node n into theResult ∗/ private void insert(Node n) { if (theDoneNodes.contains(n)) { return; } theDoneNodes.add(n); for (int i = 0; i < n.theEdges.length; ++i) { insert (n.theEdges[i ]) ; } −−theWritePos; theResult[theWritePos] = n; } } package infra; /∗∗ ∗ a node in a directed graph ∗/ public class Node { /∗ the edges denoted by the Node reached from following the edge ∗/ Node[] theEdges; public Node(Node[] edges) { theEdges = edges; } public Node(int noEdges) { theEdges = new Node[noEdges]; } /∗∗ @see Object#equals(Object) ∗/ 2 public boolean equals(Object obj) { if (obj == this) return true; if (!( obj instanceof Node)) return false; Node n = (Node) obj; if (n.theEdges.length != theEdges.length) return false; for (int index = 0; index < theEdges.length; ++index) { if (theEdges[index] != n.theEdges[index]) return false; } return true; } } /∗∗ @see Object#hashCode() ∗/ public int hashCode() { int hash = 0; for (int index = 0; index < theEdges.length; ++index) hash += System.identityHashCode(theEdges[index]); return hash; } Komplexität: O(|V | + |E|) Aufgabe 2 Erkunden sie folgende Konzepte der Java-Programmiersprache: • kritischer Abschnitt • Thread, Monitor • Process • Semaphore • Locking Lösung Seit Java 1.0 (java.lang) • kritischer Abschnitt synchronized (Statement, Methode) • Thread: Runnable, Thread • Process: Process 3 • Monitor: Thread • synchronized block / Methode Seit Java 2 1.5 (java.util.concurrency.*): • Semaphore • Lock (auch Read-Write-Lock!) Aufgabe 3 Das Readers and Writers Problem ist ein klassisches Problem bei gleichzeitiger Ausführung mehrerer Prozesse oder Threads: • mehrere Prozesse teilen sich eine Ressource. • gleichzeitige Lesen von der Ressorce durch verschiedene Prozesse ist möglich. • nur genau ein schreibender Prozeß darf auf die Ressource zugreifen. Währenddessen darf kein weiterer Prozeß auf die Ressource zugreifen. Diskutieren Sie Lösungen zu diesem Problem. Lösung package ReadersWriters; /∗∗ ∗ @author Norman May ∗ ∗ a syncronized reader for the reader−writers problem. Synchronization is done using a monitor ∗/ public class RWMonitor { /∗∗ the shared data item ∗/ private int theSharedData; /∗∗ the read operation ∗/ public void doReadData() { startRead(); try { Thread.sleep(10); } catch (InterruptedException e) {} System.out.println(”read: ” + theSharedData); endRead(); } 4 /∗ the write operation ∗/ public void doWriteData() { startWrite() ; System.out.println(”write : old value : ” + theSharedData); theSharedData = (int) (Math.random() ∗ Integer.MAX VALUE); System.out.println(”write : new value: ” + theSharedData); try { Thread.sleep(20); } catch (InterruptedException e) {} endWrite(); } /∗∗ for the protocol : number of concurrent readers ∗/ private int readCnt = 0; /∗∗ for the protocol : number of writers (0 or 1) ∗/ private int writeCnt = 0; /∗∗ the protocol to request a read operation ∗/ private synchronized void startRead() { while (writeCnt > 0) { try { wait() ; } catch (InterruptedException e) {} } readCnt++; } /∗∗ the protocol to finish a read operation ∗/ private synchronized void endRead() { readCnt−−; notify () ; } /∗∗ the protocol to request a write operation ∗/ private synchronized void startWrite() { while(writeCnt > 0 || readCnt > 0) { try{ wait() ; } catch (InterruptedException e) {} } writeCnt++; } /∗∗ the protocol to finish a write operation ∗/ private synchronized void endWrite() { writeCnt−−; notify () ; } /∗∗ start 5 concurrent thread that read or write ∗/ public static void main(String[] args) { RWMonitor theData = new RWMonitor(); 5 } } ReaderWriter rw[] = { new ReaderWriter(theData), new ReaderWriter(theData), new ReaderWriter(theData), new ReaderWriter(theData), new ReaderWriter(theData) }; for (int i = 0; i < rw.length; ++i) { rw[i ]. start () ; } package ReadersWriters; /∗∗ ∗ @author Norman May ∗ ∗ a thread that randomly reads or writes ∗/ public class ReaderWriter extends Thread { /∗∗ the monitor that protects the shared data item ∗/ RWMonitor theData; /∗∗ constructor ∗/ ReaderWriter(RWMonitor aData) { theData = aData; } /∗∗ do access the data in read or write mode ∗/ public void run() { for(int i = 0; i < 100; ++i) { double r = Math.random(); if ( r < 0.1) { theData.doWriteData(); } else { theData.doReadData(); } } } } 6