Nebenläufigkeit in Java

Größe: px
Ab Seite anzeigen:

Download "Nebenläufigkeit in Java"

Transkript

1 Nebenläufigkeit in Java Maurice Schoenmakers muenchen.de Inhaltsverzeichnis 1 Einleitung Prozesse und Threads in Java Die Klasse Thread Der aktuelle Thread Mehrere Threads Mehrere Threads mit gemeinsamen Variablen Synchronisation paralleler Threads in Java Kritischer Bereich Bewachte kritische Bereiche Das Monitor Konzept in Java Semaphore Ganzzahlige Semaphore Boolesche Semaphore Verklemmung Koch Beispiel Verschachteltes Monitor Problem Zuteilungsstrategien in Java für Threads Zeitscheibenstrategie Sperre mit Warteschlange Anmerkungen Literatur... 28

2 1 Einleitung Ziel dieser Zusammenfassung ist es, die Programmierkonzepte in Java zur Erzeugung und Synchronisation von Nebenläufigkeit zu erläutern. Einfache Grundkentnisse in Java werden dabei vorausgesetzt. Die erläuterten Programmierkonzepte werden im Bezug gesetzt zu den Grundbegriffen zur Programmierung verteilter Systeme aus dem Kapitel 1 des Buches "Informatik, Eine grundlegende Einführung" [Bro98]. 2 Prozesse und Threads in Java Ein Java Programm besitzt in der Regel eine Klasse mit einer statischen Methode main(). Bei jedem Start eines Java Programms erzeugt das Betriebsystem einen Prozeß und startet die virtuelle Maschine (VM). Die virtuelle Maschine erzeugt einen Haupt Thread (engl.main thread) auch Programmfaden, Kontrollfluß oder leichtgewichtiger Prozeß genannt. Der Haupt Thread führt daraufhin die Methode main() aus. Es wird also zwischen Java Prozesse und Threads (threads) unterschieden. Ein Java Prozeß kann als Realisierung eines Prozesses des Prozeßmodells der Vorlesung gesehen werden. Ein Java Thread entspricht einem sequentiellen Teilprozeß. Alle Teilprozesse zusammen formen den Gesamtprozeß. Eine Methode im Quelltext besteht aus eine Sequenz von Anweisungen. Beim Übersetzen des Quelltextes, wird jede Anweisung in mehrere elementare Teilanweisungen (byte codes) für die VM zerlegt. Ein Java Threads führt diese einzelnen elementaren Anweisungen einer Methode und die Anweisungen der darin aufgerufenen Methoden sequentiell aus. Die elementaren Anweisungen sind als Aktionen des Teilprozesses zu sehen. Bei Applets startet der Internet Browser ein Java Programm. Für jedes Applet wird ein eigener Thread erzeugt, der dann die Methode init() ausführt. Mehrere Applets laufen immer gemeinsam innerhalb des vom Browser erzeugten Prozesses. Innerhalb eines Java Programms ist es möglich mit Hilfe der Klasse Thread weitere nebenläufige Threads zu erzeugen. Mehrere Threads laufen parallel ab. Sie können gleichzeitig auf gleiche Objekte und Daten zugreifen. Dadurch kann es zu der, in der Vorlesung erwähnten Konflikte, kommen. Auf die Konflikte und wie sie gelöst werden, wird später detailliert eingegangen. Mehrere Threads in einem Programm werden gebraucht, um mehrere Aufgaben parallel zu erledigen. Beispiele: In einem Textprogramm wird ein Druckauftrag erteilt. Mit dem Editieren kann fortgefahren werden. Im Hintergrund wird die Aufbereitung des Textes für den Drucker erledigt. In einer Anwendung zum Erfassen und Pflegen von Daten kann in einer Maske eine Suche gestartet werden. In einer anderen Maske können währenddessen Daten weiter editiert werden. 2 / 28

3 Java Threads und das Betriebssystem Java Prozesse werden auf Betriebssystem Prozesse abgebildet. Sie stellen in Java streng getrennte Bereiche dar. So kann ein Thread eines Java Prozesses nie auf Objekte in anderen Prozessen zugreifen. Eine Kommunikation ist nicht direkt, sondern nur über Verteilungstechnologien wie CORBA oder DCOM, möglich. Diese basieren indirekt auf Netzwerkdiensten des Betriebsystems. Die Java Threads können von der virtuellen Maschine auf Betriebsystem Threads abgebildet werden. Man spricht von einer VM, die native threads unterstützt. Dies ist jedoch nicht immer der Fall. Die meisten ersten Unix Implementierungen der VM verwenden noch ein eigenes Betriebssystem unabhängiges Verfahren, häufig green threads genannt. Dabei werden Threads simuliert. Diese Simulation benutzt ein speziellen Scheduler, der die Reihenfolge der Ausführung festlegt, und oft zu einem unerwarteten und manchmal unerwünschten deterministischen Verhalten. (Siehe auch 4. Zuteilungsstrategien in Java) 2.1 Die Klasse Thread Java bietet eine Klasse Thread an, die einen Thread repräsentiert. Mit Hilfe dieser Klasse können Threads erzeugt werden. Es werden hier nur die wichtigsten Methoden besprochen. 2.2 Der aktuelle Thread Die statische Methode currentthread() liefert den Zugriff auf den aktuellen Thread, der die Methode gerade ausführt. Ein einfaches Programm, das den aktuellen Thread am Bildschirm ausgibt: public class ThreadTest public static void main( String[] arguments ) System.out.println("THREAD:" + Thread.currentThread() ); Am Ende der Methode main() ist auch der Thread und damit der Prozeß beendet. Ausgabe am Bildschirm: THREAD:Thread[main,5,main] Hinter dem Text THREAD: steht, das was die Methode tostring() der Klasse Thread zurück liefert. Das sind der Name, die Priorität und die Thread Gruppe. Auf die Priorität und Gruppe wird später unter 4. genauer eingegangen, sie sind zunächst unwichtig. 3 / 28

4 2.3 Mehrere Threads Jetzt fügen wir eine Klasse Counter hinzu mit einer Methode run(). Die Methode soll die Zahl 0 bis einschließlich 1000 ausgeben. Weiterhin erzeugen wir einen zweiten Thread, um zweimal parallel die Methode run() auszuführen. Die Klasse Counter implementiert die Schnittstelle Runnable um damit die Methode run() für Threads als die auszuführende Methode anzugeben. class Counter implements Runnable public void run() Thread thread = Thread.currentThread(); for( long count = 0 ; count <= 1000 ; ++count ) System.out.println( thread + "COUNT:" + count ); public class MultipleThreadTest public static void main( String[] arguments ) Counter counter = new Counter(); Thread secondthread = new Thread( counter, "second" ); secondthread.start(); counter.run(); Der Haupt Thread legt in der Methode main() zunächst ein Objekt counter der Klasse Counter als Zähler an. Ein zweites Thread Objekt, secondthread, wird erzeugt und dabei wird der Zähler mitgegeben. Mit start() startet der Haupt Thread den zweiten Thread. Dieser ruft intern die run() Methode des Zählers auf. Der Haupt Thread läuft parallel weiter und ruft selbst auch die run() Methode auf. Die Methode run() wird jetzt parallel von zwei Threads ausgeführt. Jeder Thread arbeitet seine eigene Schleife ab. Der Schleifen Zähler, bzw. den Zählerstand, count, ist eine lokale Variable der Methode run() und wird auf dem Stack abgelegt. Jeder Thread besitzt sein eigenen Stack. Damit existiert der Zählerstand jetzt zweimal. Auszug aus einer möglichen Ausgabe: Thread[second,5,main]COUNT:95 Thread[second,5,main]COUNT:96 Thread[second,5,main]COUNT:97 Thread[main,5,main]COUNT:95 Thread[second,5,main]COUNT:98 Thread[main,5,main]COUNT:96 Thread[second,5,main]COUNT:99 4 / 28

5 Thread[main,5,main]COUNT:97 Thread[second,5,main]COUNT:100 Thread[main,5,main]COUNT:98 Thread[second,5,main]COUNT:101 Thread[main,5,main]COUNT:99 Thread[second,5,main]COUNT:102 Thread[main,5,main]COUNT:100 Thread[second,5,main]COUNT:103 Thread[main,5,main]COUNT:101 Thread[main,5,main]COUNT:102 Thread[main,5,main]COUNT:103 Bemerkung zu den Ausgaben Da ein regelmäßiges Abwechseln von Threads für eine Implementierung einer Java VM nicht vorgeschrieben ist, können die Ausgaben immer gleich sequentiell erscheinen. Verwenden Sie für ein weniger deterministisches Verhalten den RoundRobinScheduler aus 4.1 Zeitscheibenstrategie und schreiben Sie in die erste Zeile der Methode main() : new RoundRobinScheduler(10).start(); Bemerkung zur Methode run() Die Signatur der Methode public void run() wird durch die Schnittstelle Runnable vorgegeben. Diese Schnittstelle wird von der Klasse Thread vorausgesetzt. Man hat grundsätzlich die Wahl, von der Klasse Thread abzuleiten und dessen Methode run() zu überschreiben, oder die Schnittstelle Runnable zu implementieren und dann beim Erzeugen eines Threads das ausführbare Objekt anzugeben. Die Methode run() hat keine Parameter, daher müssen benötigte Daten anderweitig weitergereicht werden. Beispielsweise über Attribute des Objektes, das die Runnable Schnittstelle implementiert. Bemerkung zu JDK 1.2 Einige Methoden der Klasse Thread werden ab Java 1.2 nicht mehr unterstützt: Die Methode stop() und suspend() gaben keine Sperren frei und konnten somit einfach eine Verklemmung produzieren. Die Methode resume() machte ohne die Methode suspend() keinen Sinn mehr. Sperren und Verklemmung werden noch genauer besprochen. 2.4 Mehrere Threads mit gemeinsamen Variablen Wir ändern die Klasse Counter so ab, daß der Zählerstand count ein Attribut wird. Beide Threads versuchen ihrerseits den Zählerstand zu inkrementieren. Ziel ist, daß beide gemeinsam den Zähler von 0 auf 1000 hochzählen. 5 / 28

6 class Counter implements Runnable private long count = 0; public void run() Thread thread = Thread.currentThread(); for( ; count <= 1000 ; ++count ) System.out.println( thread + "COUNT:" + count ); Auszüge aus einer mögliche Ausgabe:... Thread[main,5,main]COUNT:44 Thread[main,5,main]COUNT:45 Thread[main,5,main]COUNT:46 Thread[main,5,main]COUNT:47 Thread[main,5,main]COUNT:48 Thread[main,5,main]COUNT:49 Thread[second,5,main]COUNT:49!!! Thread[main,5,main]COUNT:50 Thread[second,5,main]COUNT:51 Thread[main,5,main]COUNT:52... Thread[second,5,main]COUNT:995 Thread[second,5,main]COUNT:996 Thread[second,5,main]COUNT:997 Thread[second,5,main]COUNT:998 Thread[second,5,main]COUNT:999 Thread[second,5,main]COUNT:1000 Thread[main,5,main]COUNT:1001!!!!! Diese Ausgaben sind, wenn man den Code sieht, nicht direkt plausibel. Was ist z.b. bei der letzten Ausgabe 1001 passiert? Sei count = 999. Jetzt kann folgender Ablauf stattfinden: Der Haupt Thread "main" prüft ob count <= 1000 ist. Dies ist der Fall. Jetzt kommt Thread "second" an dieser Stelle an und prüft ebenfalls ob count <= 1000 ist. Dies ist der Fall und count wird inkrementiert und ausgegeben. Der Haupt Thread inkrementiert count ebenfalls und gibt ihn aus. Das Attribut count war inzwischen jedoch bereits von "second" inkrementiert worden, somit ist der Wert jetzt 1001! Offensichtlich ist es notwendig, beide Threads zu koordinieren. Sie müssen so synchronisiert werden, daß nur ein Thread das Prüfen der Bedingung und die Inkrementierung atomar, d.h. vollständig ohne Unterbrechung, ausführt. 6 / 28

7 Wie immer bei fehlender Synchronisation muß der im Beispiel gezeigte Fehler nicht zwingend auftreten und kann lange Zeit völlig unbemerkt bleiben. Je nachdem, wann die Threads aktiv sind bzw. bei einem Prozessor sich abwechseln, ergeben sich unterschiedliche Resultate. Dies macht es extrem schwer in einem fertigen System fehlerhafte Code Stellen zu finden. Vor allem kann allein das Suchen eines Fehlers mit Hilfe des Debuggers, den Fehler verschwinden lassen. Durch die Beobachtung mit dem Debugger wird das Abwechseln der Threads beeinflußt. 3 Synchronisation paralleler Threads in Java Mehrere Threads können nur über gemeinsame Variablen kommunizieren. Java stellt keine anderen Kommunikationsmittel zur Verfügung. Folgende Konflikte können dabei auftauchen: Gleichzeitiges Lesen und Schreiben. Ein Thread liest und ein anderer ändert gerade das Objekt, ist aber noch nicht fertig. Gleichzeitiges Schreiben. Mehrere versuchen das Objekt gleichzeitig zu ändern. Gemeinsam benutzte Objekte sollten aus der Sicht eines Threads einen korrekten konsistenten Zustand haben. Der Zustand eines Objektes besteht aus den Werten seiner Attribute und den Zuständen der enthaltenen Objekte. Das Ausführen einer Methode kann den Zustand eines Objektes ändern. Eine Methode sollte das Objekt von einem stabilen korrekten Zustand in einen anderen stabilen korrekten Zustand überführen. Beim Übergang von einem Zustand in einem anderen Zustand können Zwischenzustände auftreten, die nach außen nicht sichtbar werden sollen. Sie sind in der Regel von der Implementierung der Methode abhängig. Rufen mehrere Threads Methoden gleichzeitig auf, dann kann ohne Synchronisation ein Zwischenzustand einer Methode den Ablauf einer anderen Methode beeinflussen. Um Konflikte zwischen Threads zu vermeiden gibt es verschiedene Möglichkeiten. Schreiben nicht zulassen Eine Klasse wird so definiert, daß eine Änderung seiner Attribute nach dem Erzeugen der Objekte nicht mehr möglich ist. ( engl. immutable class). Dies scheint eine drastische Einschränkung, kann aber in manchen Fällen durchaus sinnvoll sein. Vor allem, wenn ein Objekt einen Wert darstellt und die Identität nicht wesentlich ist, kann man sich die meist zeitintensive Synchronisation sparen. Bei Java können z.b. mehrere Threads problemlos auf ein gleiches Objekt der Klasse java.lang.string zugreifen, da ein String nie mehr geändert werden kann. Jede Methode der Klasse produziert bei einer Änderung des Wertes ein neues String Objekt. Für eine performante Änderung eines String steht die Klasse java.lang.stringbuffer zur Verfügung, diese ist aber nicht sicher für die gleichzeitige Verwendung durch mehrere Threads. (engl. thread safe) 7 / 28

8 Lesen und Schreiben synchronisieren Für die meisten Objekte jedoch ist die Identität wichtig. Nur eine explizite Synchronisation, die nachfolgend erläutert wird, kann Konflikte vermeiden. Die Sperre Java verknüpft jede Instanz der Klasse java.lang.object mit einer sogenannten Sperre ( engl. lock). Jedes Objekt ist in Java direkt oder indirekt von der Klasse java.lang.object abgeleitet, somit ist mit jedem Objekt genau eine Sperre verknüpft. Diese Sperre entspricht einem Booleschen Semaphor. Eine Sperre wird einem einzigen Thread zugeteilt. Die anderen Threads müssen gegebenenfalls warten, bis der Thread die Sperre wieder freigibt. Mit diesem gegenseitigen Ausschluß (engl. mutually exclusive lock kurz mutex lock) lassen sich Zugriffe auf Objekte so koordinieren, daß Konflikte vermieden werden. Betrachten wir einen Bereich, in dem gemeinsame Variablen geschrieben oder gelesen werden. Benötigt jeder Thread eine Sperre bevor er diesen Bereich ausführt und gibt er danach die Sperre wieder frei, dann kann zu jedem Zeitpunkt nur ein einziger Thread in dem Bereich aktiv sein. Somit ist ein gleichzeitiges Lesen und Scheiben oder ein gleichzeitiges Schreiben der gemeinsamen Variablen in diesem Bereich unmöglich. In Java müssen alle Bereiche, in dem gemeinsame Variablen geschrieben oder gelesen werden, explizit mit dem Schlüsselwort synchronized versehen werden, um Konflikte zu vermeiden. Sei O ein beliebiger Ausdruck, der ein Java Objekt liefert, und S eine Menge von Anweisungen, dann ist die Syntax: synchronized( O ) S Erreicht ein Thread die synchronized Anweisung, dann gelten folgende Regeln: Der Thread versucht den exklusiven Zugriff auf das Objekt O zu erhalten. Wenn kein anderer Thread den exklusiven Zugriff hat, gelingt dies. Besitzt ein anderer Thread den exklusiven Zugriff auf das Objekt, dann wartet der Thread, bis das Objekt O freigegeben wird. Es können mehrere Threads auf die Freigabe warten. (Siehe auch 3. Zuteilungstrategien). Erhält ein Thread den exklusiven Zugriff auf O, dann tritt er in den Anweisungsblock ein. Verläßt der Thread den Anweisungsblock, in dem er den exklusiven Zugriff erhalten hat, dann gibt er das Objekt O wieder frei. Die mit einem Objekt verknüpfte Sperre ist sonst nicht direkt zugänglich und kann nur mit dem Schlüsselwort synchronized gesetzt und freigegeben werden. 8 / 28

9 Ausnahmebehandlung Achtung: Wenn eine Ausnahme ( engl. exception) auftritt, die nicht innerhalb eines Anweisungsblocks abgefangen wird, dann wird wie üblich der Anweisungsblock automatisch verlassen und dabei auch die Sperre freigegeben. Daher sollte man auch nach einer Ausnahme einen konsistenten Zustand hinterlassen. Verschachtelte synchronized Anweisungsblöcke Verschachteln von synchronisierten Anweisungsblöcken ist möglich, auch wenn mehrmals mit dem gleichen Objekt synchronisiert wird: Wenn ein synchronisierter Anweisungsblock erreicht wird, kann es also sein, daß der Thread bereits den Zugriff auf das Objekt hat. Dann kann der Thread sofort in dem Anweisungsblock eintreten. Beim Verlassen dieses Anweisungsblocks, wird das Objekt noch nicht freigegeben. Erst beim Verlassen des äußeren Anweisungsblocks, dort wo er den Zugriff ursprünglich erhalten hat, wird das Objekt freigegeben. Damit wird verhindert, daß ein Thread auf sich selbst wartet. Mit einem synchronized Block wird also gewährleistet, daß nur ein Thread in dem Anweisungsblock zu einem Zeitpunkt aktiv sein kann. 3.1 Kritischer Bereich Wir können jetzt das synchronized Schlüsselwort einsetzen, um den vorher beim Zählerstand gezeigten Fehler zu beheben. Die Prüfung und die Inkrementierung stellen einen sogenannten kritischen Bereich dar. Dies ist ein Bereich, wo Konflikte zwischen Threads auftreten können. Wir ändern jetzt den Code so ab, daß die Prüfung und die Inkrementierung nur zusammen ausgeführt werden können. class Counter implements Runnable private long count = 0 ; public void run() Thread thread = Thread.currentThread(); boolean bcontinue = true; while ( bcontinue ) System.out.println( thread + "COUNT:" + count ); synchronized( this ) if( count < 1000 ) ++count; else bcontinue = false; 9 / 28

10 Warum wurde this angegeben? Das Attribut count kann man nicht angeben. Der Typ von count ist long. Dieser Typ ist ein sogenannter primitiver Typ, wie auch short, int, byte, char, float und double. Damit ist count kein Objekt. Allerdings ist count ein Attribut von der Klasse Counter. Folglich gehört zu jedem Attribut namens count genau ein Objekt der Klasse Counter. Daher ist es einfach das Attribut count mit dem zugehörigen Objekt zu synchronisieren. Das Objekt wird in der Methode mit this angegeben. Die for Schleife wurde in eine while Schleife geändert, damit die Prüfung und die Inkrementierung in einem Block innerhalb der Schleife stattfinden können. Was passiert, wenn der synchronisierte Anweisungsblock die gesamte for Schleife umfassen würde? Warum ist es Problematisch, daß die Ausgabe außerhalb des synchronized Bereiches gemacht wird? Synchronisierte Methoden Wir ändern die Klasse Counter jetzt so, daß die Prüfung und das Inkrementieren in einer eigenen increment() Methode passieren. Der Rückgabewert gibt an, ob eine Inkrementierung möglich war. class Counter implements Runnable private long count = 0 ; public void run() Thread thread = Thread.currentThread(); boolean bcontinue = true; while ( bcontinue ) System.out.println( thread + "COUNT:" + count ); bcontinue = increment(); public boolean increment() synchronized( this ) if ( count < 1000 ) ++count; return true; return false; Jetzt ist die gesamte Implementierung der Methode increment() synchronisiert. Java erlaubt dafür folgende semantisch äquivalente Schreibweise: 10 / 28

11 Wir ändern die Methode increment() ab: public synchronized boolean increment() if ( count <= 1000 ) ++count; return true; return false; Dies wird eine synchronisierte Methode genannt. Es wird gewährleistet, daß nur ein Thread gleichzeitig in genau dieser Methode aktiv sein kann. Es wird nicht gewährleistet, daß kein anderer Thread gleichzeitig in einer anderen Methode aktiv ist. D.h. count kann in einer anderen Methode weiterhin gleichzeitig geändert werden. Lesende Methoden müssen synchronisiert werden Wir führen ein Methode getcount() ein, die den Zählerstand zurück liefert. public long getcount() return count; Nehmen wir an, ein Thread ruft irgendwann getcount() auf. Auf den ersten Blick ist nicht ersichtlich, daß hier ein Problem vorliegt. Die Methode getcount() kann ein fehlerhaftes Ergebnis haben und zwar aus zwei folgenden Gründen: getcount() kann ausgeführt werden, während irgendeine andere auch synchronisierte Methode z.b increment() oder eine andere Methode aus einer Subklasse ausgeführt wird. Diese andere Methode könnte count in ihrem Ablauf zwischenzeitlich auf den Wert 1 setzen und erst am Ende den korrekten Wert zuweisen. Die Methode getcount() könnte dann zwischenzeitlich den unsinnigen Wert 1 liefern. Auch wenn keiner den Wert zwischenzeitlich auf 1 setzt, kann getcount() einen falschen Wert liefern. Java garantiert, daß alle Operationen auf primitive Typen atomar ausgeführt werden, außer für double und long. D.h. Die Ausführung von ++count, könnte in 2 Schritten ablaufen. Zwischen diesen beiden Schritten kann ein Threadwechsel auftreten. Der Wert von count nach dem 1. Schritt ist nicht spezifiziert. Was wir eigentlich erreichen wollten ist eine immer konsistente Sicht auf Counter von außen. Daher muß auch getcount() synchronisiert werden: 11 / 28

12 public synchronized long getcount() return count; Damit ist auch klar, warum eine Methode getcount() unerläßlich ist, und count nicht einfach public gemacht werden kann. Aus der bisherigen Beschreibung ist ersichtlich, daß, um mehrere Threads zu unterstützen, wesentliche Codeänderungen notwendig waren. Vollständig synchronisierte Klassen Sind in einer Klasse alle nicht statischen Methoden über dasselbe Objekt synchronisiert und alle Attribute private, dann kann ein Objekt dieser Klasse nur von jeweils einem Thread bearbeitet werden. Dies entspricht dem Konzept des Monitors, bei dem nur eine Operation eines Monitors gleichzeitig ausgeführt werden kann. Die beim Monitor üblichen Benachrichtigungsmechanismen existieren auch in Java. Sie werden anschließend im Abschnitt 2.3 erläutert. Synchronisation statischer Methoden In Java gehört zu jeder Klasse eine, vom System erzeugte Instanz der Klasse java.lang.class. Diese Instanz beschreibt den Aufbau der Klasse und macht diese zur Laufzeit verfügbar. Der Klassenname gefolgt von.class,liefert diese Instanz. Wenn eine statische Methode als synchronized gekennzeichnet wird, dann entspricht dies einer Synchronisierung mit der zu dieser Klasse gehörenden Instanz der Klasse java.lang.class. Beispiel: public class Counter private static long maximum = 1000; public static synchronized long getmaximum() return maximum; Die Methode getmaximum() entspricht folgender Implementierung: public static long getmaximum() synchronized( Counter.class ) return maximum; 12 / 28

13 Synchronisierte Methoden und Vererbung. Die Synchronisation gehört in Java nur zur Implementierung und wird nicht vererbt! Daher kann auch eine Schnittstellen Definition nicht das Schlüsselwort synchronized enthalten. Beim überschreiben einer Methode, darf daher die Synchronisation bei der neuen Implementierung nicht vergessen werden. 3.2 Bewachte kritische Bereiche Bisher konnte ein Thread nur auf eine einzige Bedingung warten. Und zwar darauf, ob ein Zugriff zur Verfügung steht oder nicht. Manchmal jedoch möchte man komplexere zustandsabhängige Bedingungen formulieren auf deren Erfüllung man wartet. Man spricht dann von einem bewachten kritischen Bereich. Ein Thread wartet bis eine Bedingung erfüllt ist, bevor er in dem Bereich eintritt. ( engl. guarded suspension) In der Vorlesung wurde dies durch await E then S endwait zum Ausdruck gebracht. Wobei E einen booleschen Ausdruck und S eine Menge von Anweisungen ist. Der Ausdruck E stellt den Wächter ( engl.guard ) dar. Sobald E erfüllt ist, wird S exklusiv von einem einzigen Thread ausgeführt. Die exklusive Ausführung wird in Java durch das Schlüsselwort synchronized erreicht. Das Warten, hier auf eine Bedingung, wird durch ein Aufruf der Methode wait() eines Objektes eingeleitet: public class ClassWithGuardedSuspension private synchronized void awaitconditione() while(! E ) try wait(); catch( InterruptedException ex ) public void synchronized guardedstatementss() awaitconditione(); S 13 / 28

14 Wozu wird wait() gebraucht? Würde man statt wait() eine Schleife wie while(!e) verwenden, dann spricht man von busy waiting. Der Thread wertet die ganze Zeit, meistens unnötigerweise, die Bedingung aus. Weiterhin wird dabei die Sperre nicht abgegeben. Dadurch kann ein anderer Thread nie an die Reihe kommen, um den Zustand so zu ändern, daß die Bedingung jemals wahr wird! Busy waiting ist folglich zu vermeiden. Ein wartender Thread muß auch benachrichtigt (engl. notified) werden, daß er weiter machen kann. Daher existieren folgende vom Laufzeitsystem vorgegeben Methoden der Klasse Object: wait() notify() notifyall() Nur wenn ein Thread den exklusiven Zugriff auf ein Objekt hat, kann er dessen wait(), notify() oder notifyall() Methode aufrufen. Ansonsten wird ein IllegalMonitorStateException vom Laufzeitsystem erzeugt. wait() Der aktuelle Thread wird auf wartend gesetzt und in einem mit dem Objekt verknüpften Wartebereich gestellt Den exklusiven Zugriff, den der Thread hat, wird freigegeben. Was Voraussetzung daf ür ist, daß andere Threads überhaupt notify() oder notifyall() aufrufen können. notify() Wenn wartende Threads existieren, dann wird nichtdeterministisch einer ausgewählt und dieser aus dem Wartebereich entfernt. Der ausgewählte Thread versucht Zugriff auf das Objekt zu bekommen. Der ausgewählte Thread kann den Zugriff nur dann bekommen, wenn der Thread der notify() aufgerufen hat und noch im Besitz des Zugriffs, diesen freigibt und kein anderer Thread den Zugriff erhält. Erhält der ausgewählter Thread später den Zugriff, dann setzt er die Ausführung mit dem auf wait() folgendem Code fort. notifyall() Verläuft wie notify() mit dem Unterschied, daß alle wartenden Threads aus dem Wartebereich entfernt werden und wieder versuchen die Sperre zu bekommen. Es existiert noch die Möglichkeit bei wait() die maximale Wartezeit anzugeben. Ist diese verstrichen, dann wird automatisch für diesen Thread wie bei notify() verfahren. Wenn ein Unterbrechung ( engl. interrupt) während eines wait() passiert ( z.b. durch Aufruf der interrupt() Methode der Klasse Thread), dann wird wie bei notify() verfahren. Die Ausführung wird aber fortgefahren mit dem Werfen einer Ausnahme der Klasse InterruptedException. Das Ziel ist es mit wait() auf ein Ereignis zu warten. Das Ereignis wird durch das Objekt oder einen Zustand des Objektes repräsentiert. Mit notify() wird dann das Eintreten des Ereignisses mitgeteilt. 14 / 28

15 Da die Auswahl der Threads beim notify() nichtdeterministisch ist, kann es zum Aushungern kommen. D.h. bestimmte Threads werden nie aus dem Wartbereich ausgewählt. Nur eine selbst programmierte Warteschlange kann hier Fairness garantieren. (siehe auch ) Somit kann jedes Java Objekt als Signal, wie beim Monitorkonzept in der Vorlesung definiert, verwendet werden. 3.3 Das Monitor Konzept in Java Das Monitor Konzept der Vorlesung läßt sich in Java realisieren durch eine Klasse, in der alle Attribute private sind, alle nicht statischen Methoden als synchronized gekennzeichnet sind und das Objekt selbst immer als Signal verwendet wird: Die Kennzeichnung aller Methoden als synchronized garantiert den gegenseitigen Ausschluß. Die Verwendung des Objektes selbst als Signal, sorgt für eine Freigabe der Sperre beim wait(), und ermöglicht damit die Ausführung der Methoden durch andere Threads. Bei der Verwendung als Signal, wird für ein Objekt o in der Regel angenommen, daß man beim Aufruf von o.wait() auf eine Zustandsänderung von o wartet. Bei o.notify() gibt man dann die Zustandsänderung bekannt. Diese Interpretation ist jedoch nicht zwingend. Beispiel für einen Monitor unter Verwendung von wait() und notifyall(): Wir ändern jetzt increment(), so daß inkrementiert wird, sobald dies möglich ist. Der Rückgabewert ist damit überflüssig. Analog zu increment() führen wir eine Methode decrement() und ein Minimum ein. Die Methode decrement() versucht zu dekrementieren, sobald dies möglich ist. Dann lassen wir einen Thread hochzählen und einen anderen Thread runterzählen. public class Counter private static long maximum = 1000; private static long minimum = 0; public static synchronized long getmaximum() return maximum; public static synchronized long getminimum() return minimum; private long count = getminimum(); private synchronized void awaitincrementable() while(!( count < getmaximum() ) ) try wait(); 15 / 28

16 catch( InterruptedException e ) public synchronized void increment() awaitincrementable(); setcount( count +1 ); private synchronized void awaitdecrementable() while(!( count > getminimum() ) ) try wait(); catch( InterruptedException e ) public synchronized void decrement() awaitdecrementable(); setcount( count 1 ); public synchronized void setcount( long count ) this.count = count; System.out.println( Thread.currentThread() + "COUNT:" + count ); notifyall(); public synchronized long getcount() return count; public class CounterTest public static void main( String[] arguments ) final Counter counter = new Counter(); Thread secondthread = new Thread( "second" ) public void run() while ( true ) counter.increment(); ; secondthread.start(); while( true ) counter.decrement(); 16 / 28

17 Jedesmal wenn count sich ändert, wird setcount und damit notifyall() aufgerufen. Ein Thread der z.b. bei einem awaitincrementable wartet, wird dann geweckt. Ist der count < maximum, dann wird inkrementiert. Warum wird die Bedingung in einer Schleife geprüft? Der notifyall() deutet nur eine Änderung an. Nach einem notifyall() ist keineswegs die Erfüllung der Bedingung gewährleistet. Warum wird notifyall() verwendet? Der Aufruf von notify() statt notifyall(), ist nur dann zu empfehlen, wenn es nur eine Bedingung gibt und nachher garantiert ist, daß nur ein einziger Thread aktiv werden kann. Wie kann die Anzahl der notify() Aufrufe und der damit verbundene Synchronisationsaufwand reduziert werden? Hinweis: Wenn der Zustandsraum aufgeteilt wird, ergeben sich nur bestimmte Situationen, wo ein notifyall() sinnvoll ist. Bemerkungen Unsere Klasse Counter ist ein Monitor im Sinne der Vorlesung. Wenn in einer synchronisierten Methode ein wait() aufgerufen wird, dann kann die Operation nicht mehr als atomar betrachtet werden! Beim wait() wird die Sperre freigegeben und andere Threads können den Zustand ändern. Daher sollte das Objekt in einen konsistenten Zustand sein bevor wait() aufgerufen wird. Am einfachsten ist dies dadurch zu erreichen, indem vor einem wait() keine Änderungen am Objekt gemacht werden. Wird der Zustand so geändert, daß ein anderer Thread weitermachen könnte, ruft man notifyall() oder notify() auf. Danach sollte der Thread, solange er den Zugriff hat, den Zustand nicht mehr ändern. Die geweckten Threads können erst nach der Freigabe der Sperre aktiv werden und nicht schon unmittelbar nach dem notifyall() Aufruf. Ein geweckter Thread findet dann vielleicht einen Zustand vor, in dem die Bedingung eventuell nicht mehr erfüllt ist. Am einfachsten ist es, wenn ein notify() Aufruf als möglichst letzter Aufruf vor dem Verlassen der Methode verwendet wird. Eine Nachrichtenschlange in Java Ein Sender und Empfänger kommunizieren über eine Nachrichtenschlange. Der Empfänger soll so lange warten bis ein Objekt vorliegt. public class MessageQueue private Vector queue = new Vector(); public synchronized void send( Object object ) queue.addelement( object ); notifyall(); 17 / 28

18 public synchronized Object receive() while( queue.size() == 0 ) try wait(); catch( InterruptedException e ) Object object = queue.elementat(0); queue.removeelementat(0); return object; // send a string character by character in an endless loop public class Sender extends Thread private String text; private MessageQueue messagequeue; public Sender( String text, MessageQueue messagequeue ) super( "sender of " + text ); this.text = text; this.messagequeue = messagequeue; public void run() while ( true ) for( int i = 0 ; i < text.length() ; ++i ) messagequeue.send( text.substring( i,i+1 ) ); public class MessageQueueTest public static void main( String[] arguments ) MessageQueue messagequeue = new MessageQueue(); Thread sosthread = new Sender( "S.O.S!!!", messagequeue ); sosthread.start(); Thread hellothread = new Sender( "Hello??", messagequeue ); hellothread.start(); while ( true ) System.out.print( messagequeue.receive() ); ; Beachte die Analogie der Klasse MessageQueue und der Klasse Counter aus dem vorangehenden Beispiel. Erweiteren Sie die Klasse MessageQueue so, daß die Nachrichtenschlange nur eine maximale Anzahl an Elementen beinhalten kann. 18 / 28

19 3.4 Semaphore Mit bewachten kritischen Bereiche können, analog zu den Definitionen der Vorlesung, auch Semaphore in Java umgesetzt werden. In der Regel ist eine direkte Verwendung der bestehenden Synchronisationsmechanismen jedoch einfacher Ganzzahlige Semaphore Die ganzzahligen Semaphore lassen sich wie folgt realisieren: public final class CountingSemaphore private int count = 0; public CountingSemaphore( int initialcount ) count = initialcount; public synchronized void P() while( count <= 0 ) try wait(); catch( InterruptedException ex ) count; public synchronized void V() ++count; notify(); Der Aufruf von notify() statt notifyall() ist ausreichend, da nur ein einziger Thread nach der Freigabe aktiv werden kann: Dieser nimmt sofort die frei gewordene Ressource und die anderen müssen weiterhin warten Boolesche Semaphore Die boolesche Semaphore werden analog zu den ganzzahligen Semaphoren implementiert: public final class BooleanSemaphore private boolean isfree; public BooleanSemaphore( boolean isfree ) this.isfree = isfree; 19 / 28

20 public synchronized void P() while(!isfree ) try wait(); catch( InterruptedException ex ) isfree = false; public synchronized void V() isfree = true; notify(); 3.5 Verklemmung Koch Beispiel Eine Verklemmung kann leicht auftreten, falls mehrere Threads die gleichen Objekte als Ressourcen in einer verschiedenen Reihenfolge verwenden. Nehmen wir an, es stehen in einer Küche nur eine Schüssel und nur ein Maßbecher sowie weitere übliche Utensilien zur Verfügung. Nehmen wir weiterhin an, ein Koch kann mehrere Omelettes machen: Er nimmt eine Schüssel, füllt die Schüssel mit aufgeschlagenen Eiern und rührt diese. Mit einem Maßbecher mißt er ab, wieviel er für jedes Omelett braucht. Er backt die einzelnen Omeletts in der Pfanne. Ein Koch kann auch Kekse machen: Er nimmt einen Maßbecher, um die Menge an Mehl zu bestimmen. Er gibt den Inhalt des Maßbechers in eine Schüssel und rührt die Ingredienzen zusammen. Anschließend formt er die Kekse und backt sie im Backofen. Das ganze in pseudo Java Code: 20 / 28

21 class Koch static Schuessel schuessel; static Massbecher massbecher; static Mehl mehl; static Ei[] eier;... void macheomeletts( int anzahl ) synchronized( schuessel ) schuessel.fuellemit( brecheeier( eier ) ); schuessel.ruehren(); synchronized( massbecher ) massbecher.fuellemit( schuessel.inhalt() ); massbecher.messeanteil(anzahl);... void machekekse() synchronized( massbecher ) massbecher.messe( mehl ); synchronized( schuessel ) schuessel.fuelle( massbecher ); schuessel.ruehren();... Nehmen wir an es gibt zwei Köche, Hugo und Fritz. Koch Hugo macht Omeletts und Koch Fritz macht Kekse. Wenn zwei Köche sich gleichzeitig in der Küche aufhalten, dann muß eine Koordination stattfinden. Die allererste selbstverständliche Koordination, die uns einfällt ist, daß die Schüssel nicht von mehreren Köchen gleichzeitig verwendet wird, sondern nur exklusiv von einem Koch. Analoges gilt für den Maßbecher. Ansonsten könnte es passieren, daß die Ingredienzen der Kekse und der Omeletts unkontrolliert vermischt werden. Ein Koch wartet sozusagen als Thread auf eine Freigabe der Schüssel. Dennoch ist diese Koordination nicht ausreichend, die Reihenfolge ist entscheidend. Folgende Situation kann auftreten: Hugo nimmt eine Schüssel, füllt diese mit Eiern. Fritz nimmt gleichzeitig den Maßbecher und mißt Mehl ab. Hugo möchte jetzt abmessen wieviel er für jedes Omelett braucht. Er braucht den Maßbecher, der ist leider noch in Gebrauch. Fritz möchte jetzt die Schüssel nehmen, um das Mehl rein zu geben, die ist leider noch in Gebrauch. 21 / 28

22 Beide warten endlos aufeinander. Ein Verklemmung ist aufgetreten. (engl. deadlock) Mögliche Lösungen sind: Es darf nur ein Koch gleichzeitig in die Küche. Damit erhöht man die Sperr Granularität. Dies verringert die Nebenläufigkeit. Oder die Köche reservieren die benötigten Utensilien immer in der gleichen Reihenfolge. Dadurch wird implizit eine Sperren Hierarchie vorgeschrieben. Bei einer Verklemmung wird von einer übergeordneten Instanz die Verklemmung aufgelöst. Ein Koch muß die Zwischenergebnisse verwerfen und neu anfangen. Diese Möglichkeit wird von Java selbst nicht unterstützt Verschachteltes Monitor Problem Eine Klasse wie die MessageQueue ist ein Monitor. Beinhaltet ein Monitor ein weiteren Monitor und ist dieser nur über den äußeren Monitor zugänglich, dann kann es ebenfalls leicht zu einer Verklemmung (engl. deadlock) kommen. Wir ändern jetzt die Klasse MessageQueue so ab, daß das Signal Die Nachrichtenschlange ist nicht leer, durch eine Boolesche Semaphore dargestellt wird. public class MessageQueue private Vector queue = new Vector(); private BooleanSemaphore nonempty = new BooleanSemaphore( false ); public synchronized void send( Object object ) queue.addelement( object ); nonempty.v(); public synchronized Object receive() nonempty.p(); Object object = queue.elementat(0); queue.removeelementat(0); return object; Wenn ein Thread receive() aufruft und wenn die Schlange leer ist, dann wird beim wait(); in der Methode P() nur die Sperre für die Semaphore freigegeben, nicht die Sperre der MessageQueue. Dadurch kann ein anderer Thread nicht in send() eintreten, d.h. nie mehr eine Nachricht in die Schlange stellen und den Thread, der in P() wartet, nie mehr benachrichtigen. Der Empfänger sperrt somit den Sender aus ( engl. lock out ) Das Problem läßt sich lösen indem: entweder synchronized beim äußeren Objekt entfernt wird, falls dies möglich ist. Oder indem man dem inneren aggregierten Objekt einen Verweis auf das Äußere mitgibt. Somit könnte das innere Objekt das äußere Objekt für die Synchronisation verwenden. Dies bedingt aber eine Codeänderung der Klasse BooleanSemaphore! 22 / 28

23 4 Zuteilungsstrategien in Java für Threads Bisher wurde nur von mehreren gleichzeitig aktiven oder wartenden Threads ausgegangen. Thread benötigen für ihre Ausführung einen Prozessor. Viele Java Implementierungen unterstützen bisher nur einen Prozessor. Bei nur einem Prozessor, kann nur ein Thread aktiv sein. Der Thread wird dem Prozessor zugeteilt. Man spricht auch von Scheduling (engl.). Die Zuteilungsstrategie beeinflußt wesentlich das Verhalten des Systems bei mehreren Threads. Um die Zuteilungsstrategien (engl. scheduling strategies) besser zu verstehen, unterscheiden wir die folgenden Zustände eines Threads: Initialzustand: Der Thread wurde erzeugt, führt aber noch keine Methode aus. d.h. start() wurde noch nicht aufgerufen. Lauffähig: Ein Thread geht vom Initialzustand mit start() in den Zustand Lauffähig über. Aktiv: Ein Thread wird aktiv, wenn er von Javas virtueller Maschine (JVM) dazu aus der Menge der lauffähigen Threads ausgewählt wird. In diesem Zustand führt der Thread tatsächlich Code aus. Der Thread wird vom der JVM dann entweder in den Zustand lauffähig zurück gesetzt oder er kommt in den Zustand Blockiert. Blockiert: Ein Thread ist blockiert, wenn er auf den exklusiven Zugriff auf eines bei synchronized angegeben Objektes oder auf ein Ereignis mittels wait() wartet. Ist ein Thread blockiert, dann geht er in den Zustand Lauffähig über, falls ein anderer Thread die Sperre freigibt oder falls ein anderer Thread mit einem notify() oder notifyall() das Ereignis meldet und daraufhin die JVM den blockierten Thread auswählt. Eine andere Möglichkeit blockiert zu werden, ist der Aufruf der Methode void sleep( long milliseconds ) der Klasse Thread. Wenn die Zeit abgelaufen ist, wird die JVM den Thread wieder in den Zustand Lauffähig setzen. Sperren werden in der Zwischenzeit nicht freigegeben. Endzustand: Ein Thread ist in seinem Endzustand, falls die run() Methode ausgeführt wurde, oder mit einer Ausnahme beendet wurde. 23 / 28

24 Auswahl durch JVM nach notify Intial start() Lauffähig Auswahl durch JVM notify() notifyall() Aktiv Blockiert run(), sleep() oder in synchronized() warten auf den Zugriff Ende von run() oder unbehandelte Ausnahme Ende Dieser Automat zeigt die Übergänge zwischen den Zuständen eines Threads Die entscheidende Frage ist, wie das Java Laufzeitsystem einen Thread zum aktiven Thread bestimmt. Prioritäten Threads können unterschiedliche Prioritäten haben. Diese werden nur vom Programmierer festgelegt. Die Java virtuelle Maschine garantiert, daß der Thread mit der höchsten Priorität, immer der aktive Thread ist. D.h. wird ein Thread lauffähig und hat dieser eine höhere Priorität als der derzeit aktive Thread, dann wird der derzeit aktive Thread unterbrochen und in den Zustand lauffähig gesetzt. Der Thread mit der höheren Priorität wird aktiv gesetzt. Damit besteht in Java die Gefahr des Aushungerns (engl. starvation). Ein Thread niedriger Priorität läuft Gefahr niemals aktiv zu werden, wenn immer mindestens ein Thread mit einer höheren Priorität lauffähig ist. Existieren nur lauffähige Threads gleicher Priorität, dann wird nichtdeterministisch ein aktiver Thread gewählt. Auch bei notify() wird nichtdeterministisch ein Thread gewählt, der in den Zustand lauffähig übergeht. Daher können die Bildschirmausgaben in den Beispielen bei jedem Durchlauf variieren. Thread Wechsel Die virtuelle Maschine muß einen neuen Thread immer nur dann als aktiv auswählen wenn: ein Thread blockiert, oder ein Thread höherer Priorität, als der aktive Thread, lauffähig wird. Folglich: Ein notify() bedingt nicht notwendigerweise einen Threadwechsel. Eine Freigabe von Sperren bedingt nicht notwendigerweise einen Threadwechsel. 24 / 28

25 Die virtuelle Maschine darf, aber muß niemals, neue Threads aktiv setzen aufgrund von anderen Ereignissen. z.b. Unterbrechungen (engl. interrupts) oder Zeiteinheiten. Dies hängt von der jeweiligen Implementierung der VM ab. Java garantiert insbesondere nicht, daß alle lauffähigen Threads nacheinander für eine feste Zeiteinheit (Zeitscheiben) aktiviert werden. (engl. round robin strategy) Ohne eine explizite Angabe, haben alle erzeugten Threads die gleiche Priorität. Viele Unix Implementierungen wechseln die Threads nur dann, wenn sie müssen. Die Windows Implementierungen jedoch meistens auch zu anderen nicht genauer definierten Zeitpunkten. Folglich ist es durchaus möglich, daß bei den Beispielen die Threads nur nacheinander aktiv werden. Dies ist an sich nicht schlimm, da semantisch die gleiche Aufgabe erledigt wird. Dadurch können aber Synchronisationsfehler unentdeckt bleiben. Hintergrund Thread Java kennt neben normalen Benutzer Threads (engl.user threads) sogenannte Hintergrund Threads (engl. daemon threads). In Java endet ein Prozeß sobald alle Benutzer Threads zu Ende sind. Dann werden auch alle Hintergrund Threads automatisch beendet. Mit den Methoden void setdaemon( boolean on ) und boolean isdaemon() der Klasse Thread kann diese Eigenschaft eines Threads gesetzt und abgefragt werden. Beispielsweise gibt es in einem Java Prozeß immer ein Hintergrund Thread, der nicht mehr referenzierte Objekte aufräumt. (engl. garbage collection thread) 4.1 Zeitscheibenstrategie Um Abhilfe gegen die sequentielle Ausführung der Threads zu schaffen und das Verhalten der Testprogrammen besser zu illustrieren, können wir eine Zeitscheibenstrategie leicht implementieren. class RoundRobinScheduler extends Thread int timeslice; public RoundRobinScheduler( int timeslice ) this.timeslice = timeslice; setpriority( Thread.MAX_PRIORITY ); setdaemon(true); public void run() while( true ) try sleep( timeslice ); catch( Exception e ) 25 / 28

26 Jedesmal, wenn dieser Thread lauffähig wird, wird er aktiviert, da er die höchste Priorität hat. Anschließend blockiert er mit sleep() für einige Millisekunden. Ein anderer Thread kommt an die Reihe usw. Eine Zeitscheiben Strategie alleine garantiert nicht, daß alle Threads gleichmäßig an die Reihe kommen. Nehmen wir unsere Klasse Counter mit zwei Threads gleicher Priorität; folgender Ablauf ist denkbar und um so wahrscheinlicher, je mehr Threads das gleiche Counter Objekt verwenden: Beide Threads arbeiten in einer Schleife und der Haupt Thread hat den Zugriff auf den Zähler. Die Zeitscheibe ist vorbei, ein Threadwechsel wird erzwungen. Der zweite Thread wird aktiv, wird jedoch gleich blockiert, da der Haupt Thread den Zugriff hat. Der Haupt Thread wird wieder aktiv. Der Zugriff wird freigegeben. Der zweite Thread wird lauffähig aber nicht automatisch aktiv. Der Haupt Thread erhält wieder den Zugriff. Die Zeitscheibe ist vorbei, ein Threadwechsel wird erzwungen. Der zweiter Thread wird jetzt aktiv aber blockiert sofort wieder. usw... Nur wenn eine Unterbrechung stattfindet während der Haupt Thread den Zugriff freigegeben hat, dann kann der zweite Thread an die Reihe kommen und den Zugriff erhalten. Erst eine Warteschlange bei der Vergabe des Zugriffs würde Abhilfe schaffen. D.h. Die Wartenden reihen sich ein. Nur der Erste in der Schlange kann den Zugriff nach einer Freigabe erhalten. 4.2 Sperre mit Warteschlange Im folgenden implementieren wir eine Sperr, die eine Warteschlange beinhaltet mit den Standard Java Synchronisationsmechanismen. Ein Thread soll warten, bis er als erster in der Warteschlange steht. Die Schnittstelle lautet: interface QueuedLock aquire() release(); Damit läßt sich synchronized( o ) / 28

27 durch o.lock.aquire();... o.lock.release(); ersetzen. Wobei lock ein öffentliches Attribut von o ist. Das Attribut lock ist dann vom Typ QueuedLock. Achtung: Eine Schachtelung von o.lock.aquire()...o.lock.release(); Bereiche, ohne sich selbst aus zu sperren, wie bei synchronized, sollte möglich sein. Mit dem Standard Mechanismus synchronized muß der Thread immer warten, falls er den Zugriff nicht enthalten kann. Manchmal gäbe es aber die Möglichkeit eine Alternative auszuführen. Erweitern Sie QueuedLock um eine Methode boolean tryaquire(). 5 Anmerkungen Sicherheit Threads werden von der virtuellen Maschine hierarchisch gruppiert. Zugang zu dieser Struktur bietet die Klasse ThreadGroup. Alle Applets werden in einem Prozeß ausgeführt. Jedes Applet hat einen eigenen ThreadGroup. Applets sollten nicht die Threads von anderen Applets beeinflussen können, es sei denn, es wird explizit erlaubt. Daher werden Aufrufe für Threads aus einer anderen ThreadGroup als der eigenen geprüft. Der Sicherheitsmanager, d.h. die Instanz der Klasse SecurityManager, wird jedesmal gefragt, ob der Aufruf erlaubt ist. Richtlinien Die Programmierung für mehrere Threads ist nicht trivial. Nachträglich sequentiellen Code für mehrere Threads tauglich (engl. thread safe) zu machen, liefert nur selten befriedigende Ergebnisse. Vor allem die Strategie der Sperrenvergabe ist vorher zu überlegen: Die Sperren Granularität sollte so grob wie möglich gewählt werden. Dies schränkt zwar die Nebenläufigkeit ein, verringert jedoch die Anzahl der Konfliktsituationen. Solange der Ablauf fair ist entsteht auch ein sinnvolles Ergebnis. Es ist immer abzuwägen, ob nur das Endergebnis zählt, oder ob auch Zwischenergebnisse wichtig sind. Wenn nur das Endergebnis zählt, ist eine geringere Nebenläufigkeit tragbar. Da die meisten virtuellen Maschinen bisher nur einen Prozessor unterstützen, verlangsamt ein häufiger Wechsel der Threads die Berechnung eher. Nur wenn Zwischenergebnisse gebraucht werden, sollte die Granularität verfeinert werden. Die Anzahl der gemeinsamen Variablen sollte so klein wie möglich bleiben. Z.B. bei der Druckaufbereitung in einem eigenem Thread ist es erheblich einfacher den gesamten Text im Speicher zu kopieren und dann zu formatieren, als die Zugriffe auf dem Text zu synchronisieren. 27 / 28

28 Fehler Ein unbedachter Einsatz von Nebenläufigkeit in Java führt auf eine tückische Fehlerquelle. Fehler tauchen in bereits getesteten Programmen unvermittelt, je nach Javaimplementierung, Rechner, Ablaufgeschwindigkeit, Betriebssystem usw. auf. Die Fehlersuche ist aufwendig. die Fehler sind schwer reproduzierbar. Eine Suche mit einem Debugger kann den Ablauf stark beeinflussen. Dadurch können Fehler "verschwinden". Auch die Ausgabe von Meldungen kann die Synchronisation beeinflussen. Wiederverwendung Synchronisation bedeutet ein erhebliches mehr an Code bzw. Code Änderungen. Synchronisations Code legt eine Verwendungsart fest. Z.B. kann in einer Methode gewartet werden, bis eine Bedingung eintritt oder einfach eine Fehlermeldung zurückgeben werden. Beide Verhaltensweisen können je nach Kontext sinnvoll sein. Es kann sinnvoll sein, den Synchronisations Code und den funktionalen Kern zu trennen. Der Synchronisations Code wird dann in eine Adapter Klasse verlagert, die den funktionalen Kern aufruft. Den funktionalen Kern kann man dann auch in einem sequentiellen Kontext einsetzen, wo eine Synchronisation nicht erwünscht ist. Denn Synchronisations Code beansprucht auch erhebliche Rechenzeit. 6 Literatur [Bro98] M. Broy, Informatik Eine grundlegende Einführung Band 2, Springer Verlag, 1998 [Dou97] Doug Lea, Concurrent Programming in Java, Design Principles and Patterns, Addison Wesley, 1997 [LiF97] Tim Lindholm & Frank Yellin, The Java Virtual Maschine Specification, Addision Wesley, 1997 [ScH97] Scott Oaks & Henry Wong, Java Threads, O Reilly & Associates, / 28

Monitore. Klicken bearbeiten

Monitore. Klicken bearbeiten Sascha Kretzschmann Institut für Informatik Monitore Formatvorlage und deren Umsetzung des Untertitelmasters durch Klicken bearbeiten Inhalt 1. Monitore und Concurrent Pascal 1.1 Warum Monitore? 1.2 Monitordefinition

Mehr

Systeme 1. Kapitel 6. Nebenläufigkeit und wechselseitiger Ausschluss

Systeme 1. Kapitel 6. Nebenläufigkeit und wechselseitiger Ausschluss Systeme 1 Kapitel 6 Nebenläufigkeit und wechselseitiger Ausschluss Threads Die Adressräume verschiedener Prozesse sind getrennt und geschützt gegen den Zugriff anderer Prozesse. Threads sind leichtgewichtige

Mehr

Objektorientierte Programmierung

Objektorientierte Programmierung Objektorientierte Programmierung 1 Geschichte Dahl, Nygaard: Simula 67 (Algol 60 + Objektorientierung) Kay et al.: Smalltalk (erste rein-objektorientierte Sprache) Object Pascal, Objective C, C++ (wiederum

Mehr

Einführung in die Programmierung

Einführung in die Programmierung Technische Universität München WS 2003/2004 Institut für Informatik Prof. Dr. Christoph Zenger Testklausur Einführung in die Programmierung Probeklausur Java (Lösungsvorschlag) 1 Die Klasse ArrayList In

Mehr

Synchronisation in Java. Invisible Web

Synchronisation in Java. Invisible Web Synchronisation in Java Studienprojekt Invisible Web Tang Zhihong Synchronisation in Java Synchronisationsproblem Monitore Wait und notify PipedInputStream und PipedOutputStream Synchronisation von Collections

Mehr

Softwarelösungen: Versuch 4

Softwarelösungen: Versuch 4 Softwarelösungen: Versuch 4 Nichtstun in Schleife wird ersetzt durch zeitweilige Zurücknahme der Anforderung, um es anderen Prozessen zu erlauben, die Ressource zu belegen: /* Prozess 0 */ wiederhole flag[0]

Mehr

Einführung in die Programmierung Blockkurs Java

Einführung in die Programmierung Blockkurs Java Michael Bader 8. 12. April 2002 Freitag Inhaltsübersicht Exceptions und Errors Ausnahmebehandlung: try/catch/finally Threads Zugriffskontrolle bei gemeinsamen Variablen: synchronized, wait(), notify()

Mehr

Einführung in die Java- Programmierung

Einführung in die Java- Programmierung Einführung in die Java- Programmierung Dr. Volker Riediger Tassilo Horn riediger horn@uni-koblenz.de WiSe 2012/13 1 Wichtig... Mittags keine Pommes... Praktikum A 230 C 207 (Madeleine + Esma) F 112 F 113

Mehr

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

Das erste Programm soll einen Text zum Bildschirm schicken. Es kann mit jedem beliebigen Texteditor erstellt werden. Einfache Ein- und Ausgabe mit Java 1. Hallo-Welt! Das erste Programm soll einen Text zum Bildschirm schicken. Es kann mit jedem beliebigen Texteditor erstellt werden. /** Die Klasse hello sendet einen

Mehr

Java Kurs für Anfänger Einheit 5 Methoden

Java Kurs für Anfänger Einheit 5 Methoden Java Kurs für Anfänger Einheit 5 Methoden Ludwig-Maximilians-Universität München (Institut für Informatik: Programmierung und Softwaretechnik von Prof.Wirsing) 22. Juni 2009 Inhaltsverzeichnis Methoden

Mehr

Computeranwendung und Programmierung (CuP)

Computeranwendung und Programmierung (CuP) Computeranwendung und Programmierung (CuP) VO: Peter Auer (Informationstechnologie) UE: Norbert Seifter (Angewandet Mathematik) Organisatorisches (Vorlesung) Vorlesungszeiten Montag 11:15 12:45 Freitag

Mehr

Programmierkurs Java

Programmierkurs Java Programmierkurs Java Dr. Dietrich Boles Aufgaben zu UE16-Rekursion (Stand 09.12.2011) Aufgabe 1: Implementieren Sie in Java ein Programm, das solange einzelne Zeichen vom Terminal einliest, bis ein #-Zeichen

Mehr

1 topologisches Sortieren

1 topologisches Sortieren Wolfgang Hönig / Andreas Ecke WS 09/0 topologisches Sortieren. Überblick. Solange noch Knoten vorhanden: a) Suche Knoten v, zu dem keine Kante führt (Falls nicht vorhanden keine topologische Sortierung

Mehr

2A Basistechniken: Weitere Aufgaben

2A Basistechniken: Weitere Aufgaben 2A Basistechniken: Weitere Aufgaben 2A.3 Programmierung unter UNIX/Linux 1. Gegeben sind einige Ausschnitte von C-Programmen, die unter UNIX/Linux ausgeführt werden sollen. Beantworten Sie die zugehörigen

Mehr

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

Java Kurs für Anfänger Einheit 4 Klassen und Objekte Java Kurs für Anfänger Einheit 4 Klassen und Ludwig-Maximilians-Universität München (Institut für Informatik: Programmierung und Softwaretechnik von Prof.Wirsing) 13. Juni 2009 Inhaltsverzeichnis klasse

Mehr

Primzahlen und RSA-Verschlüsselung

Primzahlen und RSA-Verschlüsselung Primzahlen und RSA-Verschlüsselung Michael Fütterer und Jonathan Zachhuber 1 Einiges zu Primzahlen Ein paar Definitionen: Wir bezeichnen mit Z die Menge der positiven und negativen ganzen Zahlen, also

Mehr

Zwischenablage (Bilder, Texte,...)

Zwischenablage (Bilder, Texte,...) Zwischenablage was ist das? Informationen über. die Bedeutung der Windows-Zwischenablage Kopieren und Einfügen mit der Zwischenablage Vermeiden von Fehlern beim Arbeiten mit der Zwischenablage Bei diesen

Mehr

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

Prof. Dr. Uwe Schmidt. 21. August 2007. Aufgaben zur Klausur Objektorientierte Programmierung im SS 2007 (IA 252) Prof. Dr. Uwe Schmidt 21. August 2007 Aufgaben zur Klausur Objektorientierte Programmierung im SS 2007 (IA 252) Zeit: 75 Minuten erlaubte Hilfsmittel: keine Bitte tragen Sie Ihre Antworten und fertigen

Mehr

Innere Klassen in Java

Innere Klassen in Java Innere Klassen in Java SS 2012 Prof. Dr. Margarita Esponda Innere Klassen Klassen- oder Interfacedefinitionen können zur besseren Strukturierung von Programmen verschachtelt werden Eine "Inner Class" wird

Mehr

Programmieren in Java

Programmieren in Java Programmieren in Java objektorientierte Programmierung 2 2 Zusammenhang Klasse-Datei In jeder *.java Datei kann es genau eine public-klasse geben wobei Klassen- und Dateiname übereinstimmen. Es können

Mehr

Grundlagen der Theoretischen Informatik, SoSe 2008

Grundlagen der Theoretischen Informatik, SoSe 2008 1. Aufgabenblatt zur Vorlesung Grundlagen der Theoretischen Informatik, SoSe 2008 (Dr. Frank Hoffmann) Lösung von Manuel Jain und Benjamin Bortfeldt Aufgabe 2 Zustandsdiagramme (6 Punkte, wird korrigiert)

Mehr

14.4.2016. Technische Hochschule Georg Agricola WORKSHOP TEIL 3. IKT (Informations- und Kommunikationstechnik) an einer MorseApp erklärt

14.4.2016. Technische Hochschule Georg Agricola WORKSHOP TEIL 3. IKT (Informations- und Kommunikationstechnik) an einer MorseApp erklärt 14.4.2016 Technische Hochschule Georg Agricola WORKSHOP TEIL 3 IKT (Informations- und Kommunikationstechnik) an einer MorseApp erklärt Inhaltsverzeichnis 1. Kurzfassung zur Projekterstellung... 2 2. Morse-Tabelle...

Mehr

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

Verhindert, dass eine Methode überschrieben wird. public final int holekontostand() {...} public final class Girokonto extends Konto {... PIWIN I Kap. 8 Objektorientierte Programmierung - Vererbung 31 Schlüsselwort: final Verhindert, dass eine Methode überschrieben wird public final int holekontostand() {... Erben von einer Klasse verbieten:

Mehr

Mediator 9 - Lernprogramm

Mediator 9 - Lernprogramm Mediator 9 - Lernprogramm Ein Lernprogramm mit Mediator erstellen Mediator 9 bietet viele Möglichkeiten, CBT-Module (Computer Based Training = Computerunterstütztes Lernen) zu erstellen, z. B. Drag & Drop

Mehr

Große Übung Praktische Informatik 1

Große Übung Praktische Informatik 1 Große Übung Praktische Informatik 1 2005-12-08 fuessler@informatik.uni-mannheim.de http://www.informatik.uni-mannheim.de/pi4/people/fuessler 1: Announcements / Orga Weihnachtsklausur zählt als Übungsblatt,

Mehr

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

Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung: Lösungsvorschlag Ludwig-Maximilians-Universität München WS 2015/16 Institut für Informatik Übungsblatt 9 Prof. Dr. R. Hennicker, A. Klarl Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung:

Mehr

Grundlagen verteilter Systeme

Grundlagen verteilter Systeme Universität Augsburg Insitut für Informatik Prof. Dr. Bernhard Bauer Wolf Fischer Christian Saad Wintersemester 08/09 Übungsblatt 3 12.11.08 Grundlagen verteilter Systeme Lösungsvorschlag Aufgabe 1: a)

Mehr

Universität Karlsruhe (TH)

Universität Karlsruhe (TH) Universität Karlsruhe (TH) Forschungsuniversität gegründet 1825 Cluster-Praktikum Sommersemester 2007 Transparent Replizierte Objekte in JavaParty Institut für Programmstrukturen und Datenorganisation

Mehr

Objektorientierte Programmierung für Anfänger am Beispiel PHP

Objektorientierte Programmierung für Anfänger am Beispiel PHP Objektorientierte Programmierung für Anfänger am Beispiel PHP Johannes Mittendorfer http://jmittendorfer.hostingsociety.com 19. August 2012 Abstract Dieses Dokument soll die Vorteile der objektorientierten

Mehr

Folge 18 - Vererbung

Folge 18 - Vererbung Workshop Folge 18 - Vererbung 18.1 Ein einfacher Fall der Vererbung Schritt 1 - Vorbereitungen Besorgen Sie sich - vielleicht aus einer der Übungen der Folge 17 - ein fertiges und lauffähiges Listenprojekt,

Mehr

Erwin Grüner 09.02.2006

Erwin Grüner 09.02.2006 FB Psychologie Uni Marburg 09.02.2006 Themenübersicht Folgende Befehle stehen in R zur Verfügung: {}: Anweisungsblock if: Bedingte Anweisung switch: Fallunterscheidung repeat-schleife while-schleife for-schleife

Mehr

5. Tutorium zu Programmieren

5. Tutorium zu Programmieren 5. Tutorium zu Programmieren Dennis Ewert Gruppe 6 Universität Karlsruhe Institut für Programmstrukturen und Datenorganisation (IPD) Lehrstuhl Programmierparadigmen WS 2008/2009 c 2008 by IPD Snelting

Mehr

Übungen 19.01.2012 Programmieren 1 Felix Rohrer. Übungen

Übungen 19.01.2012 Programmieren 1 Felix Rohrer. Übungen Übungen if / else / else if... 2... 2 Aufgabe 2:... 2 Aufgabe 3:... 2 Aufgabe 4:... 2 Aufgabe 5:... 2 Aufgabe 6:... 2 Aufgabe 7:... 3 Aufgabe 8:... 3 Aufgabe 9:... 3 Aufgabe 10:... 3 switch... 4... 4 Aufgabe

Mehr

Schritt 1 - Ein Spielfeld

Schritt 1 - Ein Spielfeld Schritt 1 - Ein Spielfeld Wir beginnen mit zwei einfachen Java-Klassen, dem eigentlichen Spielfeld und dem Applet zum Anzeigen des Spielfeldes (und später der Buttons und der anderen Bedienelemente). Hier

Mehr

Musterlösungen zur Klausur Informatik 3

Musterlösungen zur Klausur Informatik 3 Musterlösungen zur Klausur Informatik 3 Justus-Liebig-Universität Gießen Wintersemester 2003/2004 Aufgabe 1 (6 Punkte) Man kreuze bei den folgenden Deklarationen und Definitionen jeweils an, ob sie aus

Mehr

Lineargleichungssysteme: Additions-/ Subtraktionsverfahren

Lineargleichungssysteme: Additions-/ Subtraktionsverfahren Lineargleichungssysteme: Additions-/ Subtraktionsverfahren W. Kippels 22. Februar 2014 Inhaltsverzeichnis 1 Einleitung 2 2 Lineargleichungssysteme zweiten Grades 2 3 Lineargleichungssysteme höheren als

Mehr

Objektorientierte Programmierung. Kapitel 12: Interfaces

Objektorientierte Programmierung. Kapitel 12: Interfaces 12. Interfaces 1/14 Objektorientierte Programmierung Kapitel 12: Interfaces Stefan Brass Martin-Luther-Universität Halle-Wittenberg Wintersemester 2012/13 http://www.informatik.uni-halle.de/ brass/oop12/

Mehr

Zählen von Objekten einer bestimmten Klasse

Zählen von Objekten einer bestimmten Klasse Zählen von Objekten einer bestimmten Klasse Ziel, Inhalt Zur Übung versuchen wir eine Klasse zu schreiben, mit der es möglich ist Objekte einer bestimmten Klasse zu zählen. Wir werden den ++ und den --

Mehr

Erweiterung der Aufgabe. Die Notenberechnung soll nicht nur für einen Schüler, sondern für bis zu 35 Schüler gehen:

Erweiterung der Aufgabe. Die Notenberechnung soll nicht nur für einen Schüler, sondern für bis zu 35 Schüler gehen: VBA Programmierung mit Excel Schleifen 1/6 Erweiterung der Aufgabe Die Notenberechnung soll nicht nur für einen Schüler, sondern für bis zu 35 Schüler gehen: Es müssen also 11 (B L) x 35 = 385 Zellen berücksichtigt

Mehr

Studentische Lösung zum Übungsblatt Nr. 7

Studentische Lösung zum Übungsblatt Nr. 7 Studentische Lösung zum Übungsblatt Nr. 7 Aufgabe 1) Dynamische Warteschlange public class UltimateOrderQueue private Order[] inhalt; private int hinten; // zeigt auf erstes freies Element private int

Mehr

Delegatesund Ereignisse

Delegatesund Ereignisse Delegatesund Ereignisse «Delegierter» Methoden Schablone Funktionszeiger Dr. Beatrice Amrhein Überblick Definition eines Delegat Einfache Delegate Beispiele von Delegat-Anwendungen Definition eines Ereignisses

Mehr

Speicher in der Cloud

Speicher in der Cloud Speicher in der Cloud Kostenbremse, Sicherheitsrisiko oder Basis für die unternehmensweite Kollaboration? von Cornelius Höchel-Winter 2013 ComConsult Research GmbH, Aachen 3 SYNCHRONISATION TEUFELSZEUG

Mehr

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

Fachgebiet Informationssysteme Prof. Dr.-Ing. N. Fuhr. Programmierung Prof. Dr.-Ing. Nobert Fuhr. Übungsblatt Nr. 6 Gudrun Fischer Sascha Kriewel programmierung@is.informatik.uni-duisburg.de Anmeldung zur Klausur! Übungsblatt Nr. 6 Um an der Klausur teilzunehmen, müssen sich Studierende der angewandten Informatik in

Mehr

1 Mathematische Grundlagen

1 Mathematische Grundlagen Mathematische Grundlagen - 1-1 Mathematische Grundlagen Der Begriff der Menge ist einer der grundlegenden Begriffe in der Mathematik. Mengen dienen dazu, Dinge oder Objekte zu einer Einheit zusammenzufassen.

Mehr

Verteilte Systeme CS5001

Verteilte Systeme CS5001 Verteilte Systeme CS5001 Th. Letschert TH Mittelhessen Gießen University of Applied Sciences Client-Server-Anwendungen: Vom passiven (shared state) Monitor zum aktiven Monitor Monitor (Hoare, Brinch-Hansen,

Mehr

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

Einfache Arrays. Annabelle Klarl. Einführung in die Informatik Programmierung und Softwareentwicklung Annabelle Klarl Zentralübung zur Vorlesung Einführung in die Informatik: http://www.pst.ifi.lmu.de/lehre/wise-13-14/infoeinf WS13/14 Action required now 1. Smartphone: installiere die App "socrative student"

Mehr

Betriebssystembau (BSB)

Betriebssystembau (BSB) Betriebssystembau (BSB) 6. Übung http://ess.cs.tu-.de/de/teaching/ws2013/bsb/ Olaf Spinczyk olaf.spinczyk@tu-.de http://ess.cs.tu-.de/~os AG Eingebettete System Informatik 12, TU Dortmund Agenda Vorstellung

Mehr

Synchronisierung. Kommunikationstechnik, SS 08, Prof. Dr. Stefan Brunthaler 73

Synchronisierung. Kommunikationstechnik, SS 08, Prof. Dr. Stefan Brunthaler 73 Synchronisierung Kommunikationstechnik, SS 08, Prof. Dr. Stefan Brunthaler 73 Übertragungsprozeduren Die Übertragung einer Nachricht zwischen Sender und Empfänger erfordert die Übertragung des Nutzsignals

Mehr

SEP 114. Design by Contract

SEP 114. Design by Contract Design by Contract SEP 114 Design by Contract Teile das zu entwickelnde Programm in kleine Einheiten (Klassen, Methoden), die unabhängig voneinander entwickelt und überprüft werden können. Einheiten mit

Mehr

Wir arbeiten mit Zufallszahlen

Wir arbeiten mit Zufallszahlen Abb. 1: Bei Kartenspielen müssen zu Beginn die Karten zufällig ausgeteilt werden. Wir arbeiten mit Zufallszahlen Jedesmal wenn ein neues Patience-Spiel gestartet wird, muss das Computerprogramm die Karten

Mehr

Domänenmodell: Fadenkommunikation und -synchronisation

Domänenmodell: Fadenkommunikation und -synchronisation Domänenmodell: Fadenkommunikation und -synchronisation Alexander Humphreys, Reinhard Rösch, Fabian Scheler 15. Mai 2003 Inhaltsverzeichnis 1 Domänendefinition 1 2 Domänenlexikon 1 3 Konzeptmodelle 4 4

Mehr

C++ Tutorial: Timer 1

C++ Tutorial: Timer 1 C++ Tutorial: Timer 1 Timer v1.0 Einleitung Raum und Zeit sind spätestens seit der kopernikanischen Wende wichtige Gegenstände des Denkens geworden. In einem Programm bestimmt die Zeit die Abläufe und

Mehr

Vorkurs C++ Programmierung

Vorkurs C++ Programmierung Vorkurs C++ Programmierung Klassen Letzte Stunde Speicherverwaltung automatische Speicherverwaltung auf dem Stack dynamische Speicherverwaltung auf dem Heap new/new[] und delete/delete[] Speicherklassen:

Mehr

MCRServlet Table of contents

MCRServlet Table of contents Table of contents 1 Das Zusammenspiel der Servlets mit dem MCRServlet... 2 1 Das Zusammenspiel der Servlets mit dem MCRServlet Als übergeordnetes Servlet mit einigen grundlegenden Funktionalitäten dient

Mehr

Zur Erinnerung: Threads. Threadverwaltung. Threads: Prioritäten. Beispiel Flugbuchungsprogramm. Nichtdeterminismus

Zur Erinnerung: Threads. Threadverwaltung. Threads: Prioritäten. Beispiel Flugbuchungsprogramm. Nichtdeterminismus Zur Erinnerung: Threads Programmierung (fortgeschrittene Konzepte) Threads, Monitore, Semaphore und speisende en Wolf-Ulrich Raffel (uli@wuraffel.de) Möglichkeiten, Threads zu definieren Bildung einer

Mehr

Design by Contract with JML

Design by Contract with JML Thema: Design by Contract with JML Proseminar: Assertions Verfasser: Literatur: Betreuer: Natalya Moriz Gary T.Leavens and Yoonsik Cheon: Design by Contract with JML Prof. Dr. Heike Wehrheim 1 Inhalt DBC

Mehr

Enigmail Konfiguration

Enigmail Konfiguration Enigmail Konfiguration 11.06.2006 Steffen.Teubner@Arcor.de Enigmail ist in der Grundkonfiguration so eingestellt, dass alles funktioniert ohne weitere Einstellungen vornehmen zu müssen. Für alle, die es

Mehr

Datensicherung. Beschreibung der Datensicherung

Datensicherung. Beschreibung der Datensicherung Datensicherung Mit dem Datensicherungsprogramm können Sie Ihre persönlichen Daten problemlos Sichern. Es ist möglich eine komplette Datensicherung durchzuführen, aber auch nur die neuen und geänderten

Mehr

Drucken aus der Anwendung

Drucken aus der Anwendung Drucken aus der Anwendung Drucken aus der Anwendung Nicht jeder Großformatdruck benötigt die volle Funktionsvielfalt von PosterJet - häufig sind es Standarddrucke wie Flussdiagramme und Organigramme die

Mehr

Java 7. Elmar Fuchs Grundlagen Programmierung. 1. Ausgabe, Dezember 2011 JAV7

Java 7. Elmar Fuchs Grundlagen Programmierung. 1. Ausgabe, Dezember 2011 JAV7 Java 7 Elmar Fuchs Grundlagen Programmierung 1. Ausgabe, Dezember 2011 JAV7 5 Java 7 - Grundlagen Programmierung 5 Kontrollstrukturen In diesem Kapitel erfahren Sie wie Sie die Ausführung von von Bedingungen

Mehr

Software Engineering Klassendiagramme Assoziationen

Software Engineering Klassendiagramme Assoziationen Software Engineering Klassendiagramme Assoziationen Prof. Adrian A. Müller, PMP, PSM 1, CSM Fachbereich Informatik und Mikrosystemtechnik 1 Lesen von Multiplizitäten (1) Multiplizitäten werden folgendermaßen

Mehr

50. Mathematik-Olympiade 2. Stufe (Regionalrunde) Klasse 11 13. 501322 Lösung 10 Punkte

50. Mathematik-Olympiade 2. Stufe (Regionalrunde) Klasse 11 13. 501322 Lösung 10 Punkte 50. Mathematik-Olympiade. Stufe (Regionalrunde) Klasse 3 Lösungen c 00 Aufgabenausschuss des Mathematik-Olympiaden e.v. www.mathematik-olympiaden.de. Alle Rechte vorbehalten. 503 Lösung 0 Punkte Es seien

Mehr

E Mail Versand mit der Schild NRW Formularverwaltung

E Mail Versand mit der Schild NRW Formularverwaltung -Seite 1- E Mail Versand mit der Schild NRW Formularverwaltung Seit der Version 1.12.3.97 der Reportverwaltung ist die Möglichkeit integriert, E Mails direkt, d.h. ohne Umweg über einen externen Mailclient

Mehr

Es kann maximal ein Prozess die Umladestelle benutzen.

Es kann maximal ein Prozess die Umladestelle benutzen. SoSe 0 Konzepte und Methoden der Systemsoftware Universität Paderborn Fachgebiet Rechnernetze Präsenzübung (Musterlösung) 0-06-0 bis 0-06-06 Aufgabe : Erzeuger/Verbraucher-Pattern Ein Getränkemarkt hat

Mehr

Übersicht. Nebenläufige Programmierung. Praxis und Semantik. Einleitung. Sequentielle und nebenläufige Programmierung. Warum ist. interessant?

Übersicht. Nebenläufige Programmierung. Praxis und Semantik. Einleitung. Sequentielle und nebenläufige Programmierung. Warum ist. interessant? Übersicht Aktuelle Themen zu Informatik der Systeme: Nebenläufige Programmierung: Praxis und Semantik Einleitung 1 2 der nebenläufigen Programmierung WS 2011/12 Stand der Folien: 18. Oktober 2011 1 TIDS

Mehr

4 Aufzählungen und Listen erstellen

4 Aufzählungen und Listen erstellen 4 4 Aufzählungen und Listen erstellen Beim Strukturieren von Dokumenten und Inhalten stellen Listen und Aufzählungen wichtige Werkzeuge dar. Mit ihnen lässt sich so ziemlich alles sortieren, was auf einer

Mehr

J.5 Die Java Virtual Machine

J.5 Die Java Virtual Machine Java Virtual Machine Die Java Virtual Machine 22 Prof. Dr. Rainer Manthey Informatik II Java-Compiler und Java Virtual Machine Quellcode-Datei class C... javac D.java Java-Compiler - Dateien class class

Mehr

Programmierung in C. Grundlagen. Stefan Kallerhoff

Programmierung in C. Grundlagen. Stefan Kallerhoff Programmierung in C Grundlagen Stefan Kallerhoff Vorstellungsrunde Name Hobby/Beruf Schon mal was programmiert? Erwartungen an den Kurs Lieblingstier Für zu Hause C-Buch online: http://openbook.rheinwerk-verlag.de/c_von_a_bis_z/

Mehr

Aufklappelemente anlegen

Aufklappelemente anlegen Aufklappelemente anlegen Dieses Dokument beschreibt die grundsätzliche Erstellung der Aufklappelemente in der mittleren und rechten Spalte. Login Melden Sie sich an der jeweiligen Website an, in dem Sie

Mehr

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

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

Mehr

Der lokale und verteilte Fall

Der lokale und verteilte Fall Lokale Beans Der lokale und verteilte Fall RemoteClient Lokaler Client (JSP) RemoteSession/Entity-Bean Lokale Session/Entity-Bean 2 Lokale Beans Die bisher vorgestellten EJBswaren immer in der Lage auf

Mehr

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

Der Aufruf von DM_in_Euro 1.40 sollte die Ausgabe 1.40 DM = 0.51129 Euro ergeben. Aufgabe 1.30 : Schreibe ein Programm DM_in_Euro.java zur Umrechnung eines DM-Betrags in Euro unter Verwendung einer Konstanten für den Umrechnungsfaktor. Das Programm soll den DM-Betrag als Parameter verarbeiten.

Mehr

Einführung in die Programmierung

Einführung in die Programmierung : Inhalt Einführung in die Programmierung Wintersemester 2008/09 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund - mit / ohne Parameter - mit / ohne Rückgabewerte

Mehr

1 Vom Problem zum Programm

1 Vom Problem zum Programm Hintergrundinformationen zur Vorlesung GRUNDLAGEN DER INFORMATIK I Studiengang Elektrotechnik WS 02/03 AG Betriebssysteme FB3 Kirsten Berkenkötter 1 Vom Problem zum Programm Aufgabenstellung analysieren

Mehr

Technische Dokumentation SilentStatistikTool

Technische Dokumentation SilentStatistikTool Technische Dokumentation SilentStatistikTool Version 1.0 Marko Schröder 1115063 Inhalt Einleitung... 3 Klasse Program... 3 Klasse ArgumentHandler... 3 Bereitgestellte Variablen... 3 Bereitgestellte Methoden...

Mehr

Java: Vererbung. Teil 3: super() www.informatikzentrale.de

Java: Vererbung. Teil 3: super() www.informatikzentrale.de Java: Vererbung Teil 3: super() Konstruktor und Vererbung Kindklasse ruft SELBSTSTÄNDIG und IMMER zuerst den Konstruktor der Elternklasse auf! Konstruktor und Vererbung Kindklasse ruft SELBSTSTÄNDIG und

Mehr

Vererbung & Schnittstellen in C#

Vererbung & Schnittstellen in C# Vererbung & Schnittstellen in C# Inhaltsübersicht - Vorüberlegung - Vererbung - Schnittstellenklassen - Zusammenfassung 1 Vorüberlegung Wozu benötigt man Vererbung überhaubt? 1.Um Zeit zu sparen! Verwendung

Mehr

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

5 DATEN. 5.1. Variablen. Variablen können beliebige Werte zugewiesen und im Gegensatz zu Daten Makro + VBA effektiv 5 DATEN 5.1. Variablen Variablen können beliebige Werte zugewiesen und im Gegensatz zu Konstanten jederzeit im Programm verändert werden. Als Variablen können beliebige Zeichenketten

Mehr

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

Einführung in die objektorientierte Programmierung mit Java. Klausur am 19. Oktober 2005 Einführung in die objektorientierte Programmierung mit Java Klausur am 19. Oktober 2005 Matrikelnummer: Nachname: Vorname: Semesteranzahl: Die Klausur besteht aus drei Frageblöcken zu den Inhalten der

Mehr

Matrix42. Use Case - Sicherung und Rücksicherung persönlicher Einstellungen über Personal Backup. Version 1.0.0. 23. September 2015 - 1 -

Matrix42. Use Case - Sicherung und Rücksicherung persönlicher Einstellungen über Personal Backup. Version 1.0.0. 23. September 2015 - 1 - Matrix42 Use Case - Sicherung und Rücksicherung persönlicher Version 1.0.0 23. September 2015-1 - Inhaltsverzeichnis 1 Einleitung 3 1.1 Beschreibung 3 1.2 Vorbereitung 3 1.3 Ziel 3 2 Use Case 4-2 - 1 Einleitung

Mehr

Erweiterung AE WWS Lite Win: AES Security Verschlüsselung

Erweiterung AE WWS Lite Win: AES Security Verschlüsselung Erweiterung AE WWS Lite Win: AES Security Verschlüsselung Handbuch und Dokumentation Beschreibung ab Vers. 1.13.5 Am Güterbahnhof 15 D-31303 Burgdorf Tel: +49 5136 802421 Fax: +49 5136 9776368 Seite 1

Mehr

Das Typsystem von Scala. L. Piepmeyer: Funktionale Programmierung - Das Typsystem von Scala

Das Typsystem von Scala. L. Piepmeyer: Funktionale Programmierung - Das Typsystem von Scala Das Typsystem von Scala 1 Eigenschaften Das Typsystem von Scala ist statisch, implizit und sicher 2 Nichts Primitives Alles ist ein Objekt, es gibt keine primitiven Datentypen scala> 42.hashCode() res0:

Mehr

Informatik Kurs Simulation. Hilfe für den Consideo Modeler

Informatik Kurs Simulation. Hilfe für den Consideo Modeler Hilfe für den Consideo Modeler Consideo stellt Schulen den Modeler kostenlos zur Verfügung. Wenden Sie sich an: http://consideo-modeler.de/ Der Modeler ist ein Werkzeug, das nicht für schulische Zwecke

Mehr

U08 Entwurfsmuster (II)

U08 Entwurfsmuster (II) U08 Entwurfsmuster (II) Inhalt der Übung Diskussion und Implementierung von Entwurfsmustern Übungsaufgaben Aufgabe 1 (Queue) Gegeben ist das folgende Analysemodell einer Warteschlange (Queue): Eine Warteschlange

Mehr

Beweisbar sichere Verschlüsselung

Beweisbar sichere Verschlüsselung Beweisbar sichere Verschlüsselung ITS-Wahlpflichtvorlesung Dr. Bodo Möller Ruhr-Universität Bochum Horst-Görtz-Institut für IT-Sicherheit Lehrstuhl für Kommunikationssicherheit bmoeller@crypto.rub.de 6

Mehr

Windows. Workshop Internet-Explorer: Arbeiten mit Favoriten, Teil 1

Windows. Workshop Internet-Explorer: Arbeiten mit Favoriten, Teil 1 Workshop Internet-Explorer: Arbeiten mit Favoriten, Teil 1 Wenn der Name nicht gerade www.buch.de oder www.bmw.de heißt, sind Internetadressen oft schwer zu merken Deshalb ist es sinnvoll, die Adressen

Mehr

WinVetpro im Betriebsmodus Laptop

WinVetpro im Betriebsmodus Laptop WinVetpro im Betriebsmodus Laptop Um Unterwegs Daten auf einem mobilen Gerät mit WinVetpro zu erfassen, ohne den Betrieb in der Praxis während dieser Zeit zu unterbrechen und ohne eine ständige Online

Mehr

AGROPLUS Buchhaltung. Daten-Server und Sicherheitskopie. Version vom 21.10.2013b

AGROPLUS Buchhaltung. Daten-Server und Sicherheitskopie. Version vom 21.10.2013b AGROPLUS Buchhaltung Daten-Server und Sicherheitskopie Version vom 21.10.2013b 3a) Der Daten-Server Modus und der Tresor Der Daten-Server ist eine Betriebsart welche dem Nutzer eine grosse Flexibilität

Mehr

AUSBILDUNG eines OBEDIENCE HUNDES

AUSBILDUNG eines OBEDIENCE HUNDES Beginners, CH (Box, Carré), 15 m entfernt Beginners, CH ab 2017 FCI - 1 (Box, Carré), 15 m entfernt mit Platz, 15 m FCI - 2 FCI - 3 mit Platz und Abrufen, 23 m Voransenden in einen Kreis, dann in ein Viereck

Mehr

Verkehrsteilnehmer. Beispiel: Wir betrachten die Modellierung von Handlungskomponenten wie Verkehrsteilnehmern und Straßen.

Verkehrsteilnehmer. Beispiel: Wir betrachten die Modellierung von Handlungskomponenten wie Verkehrsteilnehmern und Straßen. 7.6 Bedingte Rechte Manchmal sind Rechte nur unter bestimmten Voraussetzungen gültig. Diese Situation beschreiben wir -wie sonst auch üblich- mit bedingten Rechten. Beispiel: Wir betrachten die Modellierung

Mehr

Erstellen von x-y-diagrammen in OpenOffice.calc

Erstellen von x-y-diagrammen in OpenOffice.calc Erstellen von x-y-diagrammen in OpenOffice.calc In dieser kleinen Anleitung geht es nur darum, aus einer bestehenden Tabelle ein x-y-diagramm zu erzeugen. D.h. es müssen in der Tabelle mindestens zwei

Mehr

Access [basics] Gruppierungen in Abfragen. Beispieldatenbank. Abfragen gruppieren. Artikel pro Kategorie zählen

Access [basics] Gruppierungen in Abfragen. Beispieldatenbank. Abfragen gruppieren. Artikel pro Kategorie zählen Abfragen lassen sich längst nicht nur dazu benutzen, die gewünschten Felder oder Datensätze einer oder mehrerer Tabellen darzustellen. Sie können Daten auch nach bestimmten Kriterien zu Gruppen zusammenfassen

Mehr

Dokumentation IBIS Monitor

Dokumentation IBIS Monitor Dokumentation IBIS Monitor Seite 1 von 16 11.01.06 Inhaltsverzeichnis 1. Allgemein 2. Installation und Programm starten 3. Programmkonfiguration 4. Aufzeichnung 4.1 Aufzeichnung mitschneiden 4.1.1 Inhalt

Mehr

Kapitel 4. Monitore und wechselseitiger Ausschluss

Kapitel 4. Monitore und wechselseitiger Ausschluss Seite 1 Kapitel 4 Monitore und wechselseitiger Ausschluss Prof. Dr. Rolf Hennicker 28.05.2015 4.1 Interferenzen Seite 2 Parallel ablaufende Prozesse können sich gegenseitig (störend) beeinflussen. Beispiel

Mehr

Modellierung und Programmierung 1

Modellierung und Programmierung 1 Modellierung und Programmierung 1 Prof. Dr. Sonja Prohaska Computational EvoDevo Group Institut für Informatik Universität Leipzig 19. November 2015 Gültigkeitsbereich (Scope) von Variablen { int m; {

Mehr

GEONET Anleitung für Web-Autoren

GEONET Anleitung für Web-Autoren GEONET Anleitung für Web-Autoren Alfred Wassermann Universität Bayreuth Alfred.Wassermann@uni-bayreuth.de 5. Mai 1999 Inhaltsverzeichnis 1 Technische Voraussetzungen 1 2 JAVA-Programme in HTML-Seiten verwenden

Mehr

Nicht kopieren. Der neue Report von: Stefan Ploberger. 1. Ausgabe 2003

Nicht kopieren. Der neue Report von: Stefan Ploberger. 1. Ausgabe 2003 Nicht kopieren Der neue Report von: Stefan Ploberger 1. Ausgabe 2003 Herausgeber: Verlag Ploberger & Partner 2003 by: Stefan Ploberger Verlag Ploberger & Partner, Postfach 11 46, D-82065 Baierbrunn Tel.

Mehr

Partitionieren in Vista und Windows 7/8

Partitionieren in Vista und Windows 7/8 Partitionieren in Vista und Windows 7/8 Windows Vista und Windows 7 können von Haus aus Festplatten partitionieren. Doch die Funktion ist etwas schwer zu entdecken, denn sie heißt "Volume verkleinern".

Mehr

Stundenerfassung Version 1.8 Anleitung Arbeiten mit Replikaten

Stundenerfassung Version 1.8 Anleitung Arbeiten mit Replikaten Stundenerfassung Version 1.8 Anleitung Arbeiten mit Replikaten 2008 netcadservice GmbH netcadservice GmbH Augustinerstraße 3 D-83395 Freilassing Dieses Programm ist urheberrechtlich geschützt. Eine Weitergabe

Mehr

Moni KielNET-Mailbox

Moni KielNET-Mailbox Bedienungsanleitung Moni -Mailbox Die geht für Sie ran! Wann Sie wollen, wo immer Sie sind! im Festnetz Herzlichen Glückwunsch zu Moni Ihrer persönlichen -Mailbox! Wir haben Ihre persönliche -Mailbox eingerichtet.

Mehr