<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<document>
   <head>
      <pagetitle>Scriptum zur Vorlesung: Java Threads</pagetitle>
      <metatags description="Scriptum zu Vorlesung Java Threads" keywords="Script, Vorlesung Threads" url="http://www.jeckle.de/vorlesung/javaThreads/script.html">
         <nocache/>
         <robots revisit-after="10 days"/>
         <css/>
      </metatags>
   </head>
   <body>
      <navigation titleimage="javaThreads.png">
         <navup reference="Vorlesung Java Threads" destinationuri="index.html"/>
         <navseparator/>
         <navdown reference="Vorlesungstermine" destinationuri="termine.html"/>
         <navdown reference="Gliederung" destinationuri="toc.html"/>
         <navdown reference="Netzressourcen zu in der Vorlesung behandelten Themen" destinationuri="links.html"/>
         <navseparator/>
         <navpage reference="Einführung" destinationuri="#Einfuehrung"/>
         <navpage reference="Java API-Unterstützung zur Threadprogrammierung" destinationuri="#API"/>
         <navpage reference="Synchronisationskonzepte und -primitive" destinationuri="#sync"/>
         <navpage reference="Synchronisationsprobleme und ihre Lösung" destinationuri="#syncProb"/>
         <navpage reference="Verklemmungen" destinationuri="#deadlock"/>
         <navpage reference="Weiterführende Konzepte" destinationuri="#adv"/>
         <navpage reference="Anwendungsbeispiele" destinationuri="#application"/>
         <navseparator/>
         <navpage reference="Definitionsverzeichnis" destinationuri="#definitions"/>
         <navpage reference="Schlagwortverzeichnis" destinationuri="#keywords"/>
         <navpage reference="Abbildungsverzeichnis" destinationuri="#illustrations"/>
         <navpage reference="Verzeichnis der Beispiele" destinationuri="#examples"/>
      </navigation>
      <topic>Vorbemerkung</topic>
      <p>Dieses Scriptum enthält vorlesungsbegleitende Informationen zur <a href="http://www.jeckle.de/vorlesung/javaThreads/">Vorlesung <em>Java Threads</em> am Fachbereich Informatik der Fachhochschule Augsburg</a>. Es stellt keinen Lehrbuchersatz dar, und ist daher nur beschränkt zum Selbststudium geeignet. Seine Aufgabe ist es vielmehr die Schlüsselbegriffe und -Aussagen der Vorlesung festzuhalten und um die dort diskutierten Beispiele zu ergänzen.<br/>
Vertiefende Information zum Thema kann der <a href="index.html#literature">empfohlenen Literatur</a> entnommen werden.<br/>
Mit hoher Wahrscheinlichkeit enthält dieses Scriptum (noch) den ein oder anderen Fehler. Für Hinweise aller Art ist der <a href="MailTo:mario@jeckle.de?Subject=Fehler im Java Threads Script">Autor</a> jederzeit dankbar!<br/>
Bei der betrachteten Java-Version handelt es sich durchgängig, soweit nicht anders vermerkt, um JDK 1.4, welches <a href="http://java.sun.com">kostenfrei von der Web-Seite der Firma Sunsoft</a> bezogen werden kann.</p>
      <topic name="Einfuehrung">Einführung</topic>
      <p>Ziel der Vorlesung: Verständnis Thread-gestützter (Parallel-)Programmierung mit der Programmiersprache Java und ihrer Ausführungsumgebung.</p>
      <p>Was vermittelt die Vorlesung?<br/>
         <ul>
            <li>Grundlagen nebenläufiger Verarbeitung</li>
            <li>Java-API zur Realisierung Thread-gestützter Programme</li>
            <li>Bekannte Problemstellungen nebenläufiger Verarbeitung</li>
            <li>... und ihre Lösungsmöglichkeiten und -Ansätze</li>
            <li>... an Beispielen</li>
         </ul>
      </p>
      <p>Was vermittelt die Vorlesung nicht?<br/>
         <ul>
            <li>Java-Grundlagen</li>
            <li>Betriebssystem-Grundlagen</li>
            <li>Vertiefung der Architektur und Umsetzung verteilter Systeme</li>
         </ul>
      </p>
      <definition id="par" term="Parallelität">
    Im Wortsinne: <em>gleichartige Beschaffenheit</em>.<br/>
    Rechner ermittelt automatisch, ob einzelne Abarbeitungselemente (etwa: Prozeduren, Befehle, Maschinen-Instruktionen) <gerquot>gleichzeitig</gerquot> ausgeführt werden können und führt dies, falls möglich, für den Anwender und Programmierer transparent durch. Voraussetzung hierfür ist die Existenz logisch trennbarer Aktivitäten.<br/>
Die tatsächliche Abarbeitungsreihenfolge kann daher von der codierten abweichen!<br/>
Auf Maschinen mit nur einer einzelnen CPU lassen sich im allgemeinen nur <b>
            <keyword alt="Parallelismus, quasi ">quasi-parallele</keyword>
         </b> Abläufe realisieren. Bekanntestes Beispiel hierfür sind <keyword alt="Pipelinearchitektur">Pipline-</keyword> oder <keyword>Superskalararchitektur</keyword>en.<br/>
         <b>
            <keyword alt="Parallelismus, echter">Echter Parallelismus</keyword>
         </b> erfordert üblicherweise mehr als eine CPU, bzw. geeignet gestaltete Recheneinheiten (d.h. mehrere Befehlszähler und Statusregister, etwa bei <a href="http://www.intel.com/technology/itj/2002/volume06issue01/art01_hyper/p01_abstract.htm">Intels <em>
               <keyword>Hyper-Threading</keyword>
            </em>-Architektur</a> für Pentium 4)
    </definition>
      <p>Parallelverarbeitung kann die Verarbeitung auf mehreren physisch getrennten vollständigen Maschinen (d.h. mit eigenen CPU, Speicher, E/A-Einheiten umfassen.</p>
      <definition id="neb" term="Nebenläufigkeit (Concurrency)">
         <keyword alt="Concurrency">
    Parallele Ausführung von Anweisungen auf einem oder mehreren Prozessoren. Die Organisation der Parallelität erfolgt hierbei explizit durch den Programmierer in einer geeigneten Hochsprache.
    </keyword>
      </definition>
      <p>Nebenläufige Ausführung ist auf eine einzige physische Maschine beschränkt. Diese kann jedoch mehrere vollständige CPUs enthalten.<br/>
    Bei Java-Threads handelt es sich daher um eine Möglichkeit der nebenläufigen Ablaufsteuerung, da diese explizit (konkret: in Form von API-Aufrufen) durch den Applikationprogrammierer festgelegt wird.<br/>
Durch die Nebenläufigkeit tritt der codierte Kontrollfluß in den Hintergrund, zugunsten eines durch den Programmierer nicht beeinflußbaren <em>
            <keyword>Nichtdeterminismus</keyword>
         </em>. Hierbei obliegt es ausschließlich dem prozessorzeitzuteilenden Betriebsystem in welcher Reihenfolge die einzelnen Anweisungen ausgeführt werden. Dabei muß eine einmal eingetretene Ausführungsreihenfolge
Die Literatur trifft die Unterscheidung zwischen <em>Parallelität</em> und <em>Nebenläufigkeit</em> nicht immer trennscharf und gleichermaßen eindeutig; für die Vorlesung sind die in den Definitionen <defRef ref="par"/> und <defRef ref="neb"/> gegebenen bindend.</p>
      <definition id="process" term="Prozeß">
    Bezeichnet ein im Speicherzugriff befindliches ablauffähiges Programm mit seinen dafür notwendigen betriebsystemseitigen Datenstrukturen wie zugeordneten Eigenschaften (z.B. Stack- und Programmzähler, Prozeßzustand, sowie Eigenschaften der Speicher- und Dateiverwaltung).<br/>
         <a href="http://bs4u.informatik.fh-augsburg.de/skript-bs/bs/node13.html">siehe auch: BS-Skript</a>
      </definition>
      <p>Ein Prozeß wird durch das Betriebsystem als eigenständige Instanz -- in der Regel unabhängig und geschützt von anderen -- ausgeführt. <keyword>Multitasking</keyword>systeme (wie UNIX und neuere Generationen der Windowsfamilie) gestatten die <defJmp ref="par">parallele</defJmp> Prozessausführung.</p>
      <definition id="thread" term="Thread">
    Ein Thread (engl. für <em>Faden</em>) stellt eine <defJmp ref="neb">nebenläufige</defJmp> Ausführungseinheit innerhalb genau eines <defJmp ref="process">Prozesses</defJmp> dar.
    </definition>
      <p>Aufgrund dieser Definition erben Threads viele der prozeßtypischen Eigenschaften, wie Zustand, Programmzähler etc. Den Hauptunterschied zu voll entwickelten Prozessen bildet der zwischen allen Threads eines Prozesses geteilte Speicher. Gleichzeitig besitzt jeder Thread seinen eigenen lokalen Speicherbereich in dem u.a. die lokalen Variablen verwaltet werden. Aus diesen Gründen werden Threads oft auch als <keyword alt="Prozeß, leichtgewichtiger">leichtgewichtige Prozesse</keyword> bezeichnet.<br/>
Alle Threads bewegen sich im Ausführungskontext des erzeugenden Prozesses d.h. <gerquot>externe Operationen</gerquot> wie Plattenzugriffe etc. wirken sich über Threadgrenzen hinaus aus.<br/>
In <keyword>Multithretaing</keyword>-Systemen besitzt jeder ablaufende Prozeß mindestens einen Thread, der den Kontrollfluß realisiert.<br/>
Multitasking und Multithreating bedingen sich daher gegenseitig. Ohne die systemseitige Unterstützung der parallelen Taskausführung kann keine prozeßinterne Threadabarbeitung erfolgen.</p>
      <illustration caption="Multithreaded-Prozesse in einer Multitasking-Umgebung" id="MultiThreadingAndTasking" gfx="javaThreads/multitasking.gif" width="450"/>
      <subtopic name="history">Warum Thread-basierte Programmierung?</subtopic>
      <subsubtopic>Ein wenig Geschichte ...</subsubtopic>
      <ul>
         <li>1940er Jahre: <keyword alt="Batchbetrieb">
               <keyword>Stapelbetrieb</keyword>
            </keyword>.<br/>
        Aufträge (engl. <em>Jobs</em>)werden sequentiell an wenige existierende Rechner übermittelt.<br/>
Die Eingabe erfolgt zumeist über Lochstreifen, später Lochkarten. Die Auftragserfüllung ist nicht-interaktiv und kann während ihrer Durchführung nicht beeinflußt werden.</li>
         <li>ab 1965: <keyword>Mehrprogrammbetrieb</keyword>.<br/>
        Die knappe und teure Rechenzeit genutzt um mehrere Aufträge zeitlich verzahnt abzuarbeiten. So kann eine Aufgabe rechnend ausgeführt werden, während andere beispielsweise auf Ein-/Ausgaben warten.</li>
         <li>ab 1970er Jahren: <keyword>Mehrbenutzerbetrieb</keyword>.<br/>
        Abweichung von der aufgabenzentrierten Betrachtung, hin zu einer <keyword alt="Dialogbetrieb">dialogorientierten</keyword> Sichtweise. Mehrere Benutzer können simultan (d.h. <defJmp ref="par">quasi Parallel</defJmp>) Prozesse auf derselben Maschine ausführen. Die Illusion der gleichzeitigen Ausführung wird durch das Betriebssystem erzeugt, welches in rascher Folge zwischen den ablaufenden Prozessen umschaltet (sog. <keyword>Time-Sharing-Betrieb</keyword>).</li>
         <li>in den 1980er Jahren: <keyword>Thread-Konzept</keyword>:<br/>
        Die schwergewichtigen Prozesse erwiesen sich als zunehmend inadäquat für komplexe Problemstellungen, insbesondere Fragestellungen, die eine inhärente Parallelität aufweisen wie bestimmte numerische Fragestellungen (Paradebeispiel: Matrizenmultiplikation). Ihr betriebssystemseitiger Verwaltungsaufwand verhindert die schnelle Erzeugung und der (im allgemeinen gewünschte) Schutz der Prozesse untereinander erschwert den Datenaustausch bei der Operation auf gemeinsamen Daten.</li>
      </ul>
      <subsubtopic name="ziele">Warum Threads in Java?</subsubtopic>
      <p>Eigentlich eine zweiteilige Frage ...</p>
      <ol>
         <li>Warum sollte sich der Programmierer um das Thema kümmern?</li>
         <li>Warum unterstützt die Java-API und die virtuelle Maschine Threads?</li>
      </ol>
      <p>Skizze einer Antwort:
        zu 1.)</p>
      <ul>
         <li>Threads nutzen die vorhandenen Ressourcen moderner Betriebssysteme und Hardware effizienter aus.<br/>
Beispielsweise durch Weiterführung der Berechnungspperationen, während andere Threads auf Ein-/Ausgaben warten.</li>
         <li>Threads werden durch ein geeingetes Betriebssystem für den Programmierer und Applikationsanwender transparent auf mehrere Prozessoren (fall vorhanden) verteilt.</li>
         <li>Threads erhöhen den Interaktionskomfort für den Applikationsanwender (Beispiel: GUI-intensive Anwendungen).<br/>
                Berechnungsaufwendige Arbeiten können <gerquot>in den Hintergrund</gerquot> verlagert werden.</li>
         <li>Threads sind in Erzeugung, Handhabung und Ressourcenbedarf leichtgewichtiger als vollentwickelte Prozesse und erzeugen daher weniger Systemlast.</li>
      </ul>
      <p>zu 2.)</p>
      <ul>
         <li>... Hochsprachenschnittstelle, da in Java kein direkter Hardware- und Betriebssystemzugriff möglich.</li>
         <li>... Abstraktionsschicht von Thread-Implementierung in Java Virtual Machine.</li>
         <li>... Erleichterung und dadurch Forcierung nebenläufiger Programmierung.</li>
         <li>... Portabilität Thread-basierter Anwendungen auf andere Hardwareplattformen, die Java unterstützen.</li>
      </ul>
      <p>Die Verwendung von Threads führt im technischen Sinne nicht zu einer beschleunigten Ausführung, im Gegenteil, durch Verwaltungsaufwände bei der Erzeugung und Koordination ergibt sich im allgemeinen sogar eine insgesamt vergrößerte Ausführungszeit, jedoch bedingt die effizientere Ressorucennutzung einerseits die bessere Auslastung der vorhanden Hardware und gleichzeitig entsteht für den Anwender der Eindruck einer flüssigeren Verarbeitung.<br/>
Erst beim Einsatz mehrere Prozessoren in einer Maschine ergibt sich ein echter positiver Laufzeiteffekt durch die Möglichkeit Threads auf verschiedenen CPUs zur Ausführung zu bringen. Die Verteilung und Koordination obliegt herbei dem Betriebssystem und erfolgt für den Hochsprachenprogrammierer transparent.</p>
      <illustration id="cpuUtilization" gfx="javaThreads/cpuUtilisation.gif" width="466" caption="Gleichmäßige CPU-Auslastung durch Verteilung von Threads auf zwei Prozessoren"/>
      <topic name="API">Java API-Unterstützung zur Threadprogrammierung</topic>
      <p>Zwei generelle Ansätze:</p>
      <ol>
         <li>Durch (spezialisierende) Ableitung von der Klasse <a fixedType="JDK14" offset="java/lang/Thread.html">
               <code>Thread</code>
            </a>
         </li>
         <li>Durch Implementierung der Schnittstelle <a fixedType="JDK14" offset="java/lang/Runnable.html">
               <code>Runnable</code>
            </a>
         </li>
      </ol>
      <p>Der erste Fall läßt sich auf den zweiten zurückführen, da die Klasse <a fixedType="JDK14" offset="java/lang/Thread.html">
            <code>Thread</code>
         </a> selbst die Schnittstelle <a fixedType="JDK14" offset="java/lang/Runnable.html">
            <code>Runnable</code>
         </a> implementiert.<br/>
    Klasse und Schnittstelle sind im Standardpaket <a fixedType="JDK14" offset="java/lang/package-summary.html">
            <code>java.lang</code>
         </a> organisiert, das
    im Rahmen des Compilierungsvorganges <a href="../java/kap2.html#automaticImport">automatisch importiert</a> wird.
    </p>
      <definition id="nebenlaeufigkeitJava" term="Implementierung nebenläufiger Abläufe in Java">
    Jeder nebenläufige Programmfaden wird generell durch eine eigenständige Klasse repräsentiert,
    welche die Schnittstelle <code>Runnable</code> implementiert.
    </definition>
      <p>Die Schnittstelle <code>Runnable</code> definiert als einzige Methode <a fixedType="JDK14" offset="java/lang/Runnable.html#run()">
            <code>run</code>
         </a>, welche durch das Laufzeitsystem automatisch zu Beginn der Thread-gestützten Verarbeitung zur Ausführung gebracht wird.<br/>
Daher sollte diese Methode niemals direkt auf einem Thread-Objekt aufgerufen werden, sondern jeder Thread ausschließlich mit der dafür vorgesehenen Methode <a fixedType="JDK14" offset="java/lang/Thread.html#start()">
            <code>start</code>
         </a> dem Laufzeitsystem als rechenwillig gemeldet werden.<br/>
         <link href="#threadStates">Threadzustände</link>
      </p>
      <definition id="runMethode" term="run-Methode">
    Die <code>run</code>-Methode wird nach der Threaderzeugung automatisch durch das Laufzeitsystem asynchron ausgeführt.
    </definition>
      <p>Ihre Rolle entspricht daher konzeptionell einer <code>main</code>-Methode für Threads.</p>
      <example id="threadBased" caption="Nebenläufige Implementierung auf Basis der Ableitung von Thread" filename="ThreadBased1.java" output="tiBased1">
         <importText URI="../life/vorlesung/javaThreads/examples/ThreadBased1.java"/>
      </example>
      <p>Das Beispiel erzeugt zwei Threads (<a href="#threadBasedline5">Zeile 5 und 6</a>), die beide alle 500 Millisekunden (siehe Ausführungssuspendierung in <a href="#threadBasedline30">Zeile 30</a>) einen fixen Text am Bildschirm ausgeben.<br/>
Die beiden Threads sind beide Objekte der Klasse <code>HelloThread</code> welche von <code>Thread</code> erbt (<a href="#threadBasedline15">Zeile 15</a>).</p>
      <p>Das <exRef ref="interfaceBased"/>. Beispiel setzt die zuvor auf Basis der Ableitung von der Klasse <code>Thread</code> gezeigte Implementierung durch Realisierung der Schnittstelle <code>Runnable</code> um.</p>
      <example id="interfaceBased" caption="Nebenläufige Implementierung auf Basis der Realisierung der Schnittstelle Runnable" filename="InterfaceBased1.java" output="tiBased1">
         <importText URI="../life/vorlesung/javaThreads/examples/InterfaceBased1.java"/>
      </example>
      <p>Der Code gleicht dem vorangegangenen Beispiel, lediglich, daß die Klasse (<code>HelloThread</code>) deren Objekte nebenläufig ausgeführt werden hier die Schnittstelle <code>Runnable</code> implementiert (<a href="#interfacedBasedline17">Zeile 17</a>).<br/>
Zusätzlich kann die Methode <code>start</code> in dieser Umsetzungsvariante nicht mehr direkt auf Objekten der Klasse <code>HelloThread</code> ausgeführt werden (<a href="#interfaceBasedlineline10">Zeile 10 und 11</a>). Stattdessen müssen Ausprägungen der Klasse als Ausprägungen der Klasse <code>Thread</code> aufgefaßt werden (<a href="#interfaceBasedline7">Zeile 7 und 8</a>).</p>
      <p>Die statische Struktur der beiden Beispiele ergibt sich daher als UML-Klassendiagramm:</p>
      <illustration id="CDThreads" gfx="javaThreads/threads.gif" width="252" caption="UML-Klassendiagramm der ersten beiden Code-Beispiele"/>
      <p>Nachdem an den Beispielen bereits mit der Klasse <code>Thread</code> und der Schnittstelle <code>Runnable</code> die beiden wesentlichen Elemente der threadgestützten Programmierung in Java angerissen wurden, nachfolgend eine Übersicht der Funktionsangebots der kompletten Java API für diesen Problemkreis.<br/>
    Das UML-Klassendiagramm der Abbildung <illustrationRef id="threadStructure"/> zeigt die fundamentalen Klassen, sowie die Schnittstelle <code>Runnable</code>.
    </p>
      <illustration id="threadStructure" gfx="javaThreads/threadStructure.gif" width="529" caption="Thread-API in Java v1.4"/>
      <keyword alt="Klasse Thread">
         <subtopic name="classThread">Die Klasse <code>Thread</code>
         </subtopic>
      </keyword>
      <p>Die <a fixedType="JDK14" offset="java/lang/Thread.html">Klasse <code>Thread</code>
         </a> findet sich im Paket <a fixedType="JDK14" offset="java/lang/package-summary.html">
            <code>java.lang</code>
         </a>.<br/>
         <link href="examples/sunSrc/Thread.java">Quellcode der Klasse <code>Thread</code>
         </link>
         <br/>
Die nachfolgende Zusammenstellung basiert auf der tatsächlichen Implementierung der Klasse <code>Thread</code> und enthält daher auch für den Programmierer im allgemeinen nicht zugängliche Attribute und Operationen. Aus Gründen der Förderung des Verständnis der internen Abläufe und Vollständigkeit der Charakteristika der einzelnen API-Primitive erfolgt daher auch ihre Darstellung.</p>
      <tabular summary="Attribute der Klasse Thread in Java v1.4">
         <head length="2">
            <column title="Attributdefiniton"/>
            <column title="Semantik"/>
         </head>
         <body>
            <row>
               <sortcell sortCrit="name">
                  <a name="threadName">
                     <code>private char[] name</code>
                  </a>
               </sortcell>
               <cell>Name des Threads.<br/>
                Jeder Thread eines Prozesses trägt einen Namen. Weist der Programmierer keinen solchen zu, so wählt das Laufzeitsystem einen eigenen.<br/>
                Diese Namen gehorchen der Form <code>Thread-<em>laufendeNummer</em>
                  </code>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="priority">
                  <a name="priAtt" keyword="yes">private int priority</a>
               </sortcell>
               <cell>Priorität des Threads.<br/>
                Die numerische Priorität eines Threads wird zur Zuteilung der Rechenzeit herangezogen.
                Sie kann sich in einem durch die Konstanten <a href="#minPri">
                     <code>MIN_PRIORITY</code>
                  </a> und <a href="#maxPri">
                     <code>MAX_PRIORITY</code>
                  </a> begrenzten Intervall bewegen.<br/>
                Standardmäßig wird jeder Programmfaden mit der durch die Konstante <a href="#normPri">
                     <code>NORM_PRIORITY</code>
                  </a> festgelegten Priorität ausgeführt.</cell>
            </row>
            <row>
               <sortcell sortCrit="threadQ">
                  <code>private Thread threadQ</code>
               </sortcell>
               <cell>Keine Dokumentation verfügbar. Dieses Attribut wird überdies weder in der definieren Klasse, noch an einer anderen Stelle der Java-API verwendet.</cell>
            </row>
            <row>
               <sortcell sortCrit="eetop">
                  <code>private long eetop</code>
               </sortcell>
               <cell>Keine Dokumentation verfügbar. Dieses Attribut wird überdies weder in der definieren Klasse, noch an einer anderen Stelle der Java-API verwendet.</cell>
            </row>
            <row>
               <sortcell sortCrit="single_step">
                  <code>private boolean single_step</code>
               </sortcell>
               <cell>Gibt an ob ein Thread im <em>single-step-Modus</em> ausgeführt wird.<br/>
                Vermutlich für Debuggingzwecke verwendet.</cell>
            </row>
            <row>
               <sortcell sortCrit="daemon">
                  <a name="daemonAttr">
                     <code>private boolean daemon = false</code>
                  </a>
               </sortcell>
               <cell>Gibt an ob ein Thread als <em>Daemonthread</em> ausgeführt wird.<br/>
                Ist dies der Fall, so kann eine Applikation terminieren, die ausschließlich arbeitende Daemonthreads enthält.</cell>
            </row>
            <row>
               <sortcell sortCrit="stillborn">
                  <code>private boolean stillborn = false</code>
               </sortcell>
               <cell>Gibt an ob die Terminierung des Threads noch vor Beginn seiner Ausführung angeordnet wurde.</cell>
            </row>
            <row>
               <sortcell sortCrit="target">
                  <code>private <a href="#Runnable">Runnable</a> target</code>
               </sortcell>
               <cell>Verweis auf den ausführbaren Kern (d.h. die Implementierung) eines Threads.</cell>
            </row>
            <row>
               <sortcell sortCrit="group">
                  <code>private <a href="#threadGroup">ThreadGroup</a> group</code>
               </sortcell>
               <cell>Gruppe der ein Thread zugeordnet ist.</cell>
            </row>
            <row>
               <sortcell sortCrit="contextClassLoader">
                  <code>private <a fixedType="JDK14" offset="java/lang/ClassLoader.html">ClassLoader</a> contextClassLoader</code>
               </sortcell>
               <cell>ClassLoader für diesen Thread.</cell>
            </row>
            <row>
               <sortcell sortCrit="inheritedAccessControlContext">
                  <code>private <a fixedType="JDK14" offset="java/security/AccessControlContext.html">AccessControlContext</a> inheritedAccessControlContext</code>
               </sortcell>
               <cell>Ererbter Zugriffskontrollkontext zur Ermittlung der Berechtigungen für den Zugriff auf Systemressourcen.</cell>
            </row>
            <row>
               <sortcell sortCrit="threadInitNumber">
                  <a name="threadNo">
                     <code>private static int threadInitNumber</code>
                  </a>
               </sortcell>
               <cell>Automatisch geführter Zähler zur eineindeutigen Identifikation.</cell>
            </row>
            <row>
               <sortcell sortCrit="stopThreadPermission">
                  <code>private static <a fixedType="JDK14" offset="java/lang/RuntimePermission.html">RuntimePermission</a> stopThreadPermission</code>
               </sortcell>
               <cell>Enthält die Rechte welche einem Thread zur Laufzeit eingeräumt werden.</cell>
            </row>
            <row>
               <sortcell sortCrit="threadLocals">
                  <code>
                     <a fixedType="JDK14" offset="java/lang/ThreadLocal.html">ThreadLocal</a>.ThreadLocalMap threadLocals</code>
               </sortcell>
               <cell>Verweis auf diejenigen lokalen Variablen eines Threads die namens- und strukturgleich in allen Threads existieren, aber in jedem Programmfaden mit einem anderen Wert belegt sein können.</cell>
            </row>
            <row>
               <sortcell sortCrit="inheritableThreadLocals">
                  <code>
                     <a fixedType="JDK14" offset="java/lang/ThreadLocal.html" external="yes">ThreadLocal</a>.ThreadLocalMap inheritableThreadLocals</code>
               </sortcell>
               <cell>Diejenigen <a href="#threadLocal">threadspezifischen Variablen</a> die an Kindthreads weitergegeben werden können.</cell>
            </row>
            <row>
               <sortcell sortCrit="stackSize">
                  <a name="threadStackSize">
                     <code>private long stackSize</code>
                  </a>
               </sortcell>
               <cell>Angefragter Stackbereich für einen Thread.<br/>
                Ist dieser Wert 0, so wurde durch den Erzeuger keine Festlegung getroffen. Virtuelle Maschinen sind in der Behandlung dieses Wertes vollkommen frei; sie können ihn sogar gänzlich ignorieren.</cell>
            </row>
            <row>
               <sortcell sortCrit="blocker">
                  <a name="blockerField">
                     <code>private volatile Interruptible blocker</code>
                  </a>
               </sortcell>
               <cell>Verweis auf das Objekt welches die Ausführung des Threads durch ein (unterbrechbare) E/A-Operation unterbrochen hat.</cell>
            </row>
            <row>
               <sortcell sortCrit="pri1">
                  <a name="minPri">
                     <code>public final static int MIN_PRIORITY = 1</code>
                  </a>
               </sortcell>
               <cell>Minimalpriorität eines Threads.<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#MIN_PRIORITY"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="pri2">
                  <a name="normPri">
                     <code>public final static int NORM_PRIORITY = 5</code>
                  </a>
               </sortcell>
               <cell>Standardpriorität eines Threads.<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#NORM_PRIORITY"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="pri3">
                  <a name="maxPri">
                     <code>public final static int MAX_PRIORITY = 10</code>
                  </a>
               </sortcell>
               <cell>Maximalpriorität eines Threads.<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#MAX_PRIORITY"/>
               </cell>
            </row>
         </body>
      </tabular>
      <tabular summary="Operationen der Klasse Thread in Java 1.4">
         <head length="2">
            <column title="Operation"/>
            <column title="Semantik"/>
         </head>
         <body>
            <row>
               <sortcell sortCrit="registerNatives">
                  <code>private static native void registerNatives()</code>
               </sortcell>
               <cell>Native Methode, welche direkt nach Erzeugung eines Thread-Objekts ausgeführt wird.</cell>
            </row>
            <row>
               <sortcell sortCrit="nextThreadNum">
                  <code>private static synchronized int nextThreadNum()</code>
               </sortcell>
               <cell>Vergibt automatisch die <a href="#threadNo">Threadnummer</a>.</cell>
            </row>
            <row>
               <sortcell sortCrit="blockedOn">
                  <code>private void blockedOn(Interruptible b)</code>
               </sortcell>
               <cell>Setzt <a href="#blockerField">
                     <code>blocker</code>-Attribut</a> durch Reflexionsmechanismen des <a fixedType="JDK14" offset="java/nio/package-summary.html">NIO-Paketes</a>.</cell>
            </row>
            <row>
               <sortcell sortCrit="currentThread">
                  <code>public static native <a fixedType="JDK14" offset="java/lang/Thread.html">Thread</a> currentThread()</code>
               </sortcell>
               <cell>Liefert eine Referenz auf den aktuellen Thread zurück.<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#currentThread()"/>
                  <br/>
                  <link href="#concurrentIncrementline44">Codebeispiel</link>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="yield">
                  <a name="yield" keyword="yes">public static native void yield()</a>
               </sortcell>
               <cell>Veranlaßt den aktuellen Thread sein Zeitscheibe vorzeitig abzugeben, so daß ein anderer Programmfaden zur Ausführung gebracht werden kann.
                 <br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#yield()"/>
                  <br/>
                  <link href="#yieldExline25">Codebeispiel</link>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="sleep">
                  <code>public static native void sleep(long millis)<br/>
                 throws <a fixedType="JDK14" offset="java/lang/InterruptedException.html">InterruptedException</a>
                  </code>
               </sortcell>
               <cell>Hält die Ausführung des aktuellen Threads für die durch <code>millis</code> spezifizierte Zeitspanne in Millisekunde an.<br/>
                Der Aufruf <code>sleep(0)</code> ist äquivalent zu <a href="#yield" keyword="yes">yield()</a>. <br/>
                Während der Suspendierung werden durch den Thread gehaltene Sperren <a href="#monitore">(Monitore)</a> nicht freigegeben.<br/>
                Wird der Thread in diesem Zeitraum durch einen anderen Programmfaden unterbrochen, so wird ein Ausnahmeereignis erzeugt.
                 <br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#sleep(long)"/>
                  <br/>
                  <link href="#threadBasedline30">Codebeispiel</link>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="sleep">
                  <code>public static void sleep(long millis, int nanos)<br/>
                throws InterruptedException</code>
               </sortcell>
               <cell>Hält die Ausführung des aktuellen Threads für die durch <code>millis</code> spezifizierte Zeitspanne in Millisekunde zuzüglich der in <code>nanos</code> angegebenen Zeitspanne in Nanosekunden an.<br/>
                Während der Suspendierung werden durch den Thread gehaltene Sperren <a href="#monitore">(Monitore)</a> nicht freigegeben.<br/>
                Wird der Thread in diesem Zeitraum durch einen anderen Programmfaden unterbrochen, so wird ein Ausnahmeereignis erzeugt.
                 <br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#sleep(long, int)"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="init">
                  <code>private void init(<a href="#threadGroup">ThreadGroup</a> g, <a href="#Runnable">Runnable</a> target, String name, long stackSize)</code>
               </sortcell>
               <cell>Initialisiert einen Thread.<br/>
                Parameter:<br/>
                  <bullet/>
                  <code>g</code> bezeichnet die Threadgruppe, der der neue Thread zugeordnet werden soll.<br/>
                  <bullet/>
                  <code>target</code> bezeichnet die nebenläufig auszuführende Klasse.<br/>
                  <bullet/>
                  <code>name</code> legt den <a href="#threadName">Namen des Threads</a> fest.<br/>
                  <bullet/>
                  <code>stackSize</code> schlägt der virtuellen Maschine die <a href="#threadStackSize">für den Thread zu reservierende Stackgröße</a> vor.</cell>
            </row>
            <row>
               <sortcell sortCrit="a">
                  <code>public Thread()</code>
               </sortcell>
               <cell>Erzeugt eine neuen Thread.<br/>
                Die Wirkung entspricht <a href="#threadConstruction">
                     <code>Thread(null,null,<em>gname</em>)</code>
                  </a>, wobei <em>gname</em> den <a href="#threadName">Namen des neuen Threads</a> festlegt.
                 <br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#Thread()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="a">
                  <code>public Thread(Runnable target)</code>
               </sortcell>
               <cell>Erzeugt einen neuen Thread.<br/>
                Die Wirkung entspricht <a href="#threadConstruction">
                     <code>Thread(null,<em>target</em>,<em>gname</em>)</code>
                  </a>,
                wobei <em>target</em> die nebenläufig auszuführende Klasse bezeichnet und <em>gname</em> den <a href="#threadName">Namen des neuen Threads</a> festlegt.
                 <br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#Thread(java.lang.Runnable)"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="a">
                  <code>public Thread(<a href="#threadGroup">ThreadGroup</a> group, <a href="#Runnable">Runnable</a> target)</code>
               </sortcell>
               <cell>Erzeugt eine neue Thread.<br/>
                Die Wirkung entspricht <a href="#threadConstruction">
                     <code>Thread(group,target,gname)</code>
                  </a>,
                wobei <em>group</em> die Threadgruppe bezeichnet, innerhalb der der neu erzeugte Thread ablaufen soll.
                <em>target</em> bezeichnet die nebenläufig auszuführende Klasse und <em>gname</em> den <a href="#threadName">Namen des neuen Threads</a>, der automatisch generiert wird.
                 <br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#Thread(java.lang.ThreadGroup, java.lang.Runnable)"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="a">
                  <code>public Thread(String name)</code>
               </sortcell>
               <cell>Erzeugt einen neuen Thread des durch <code>name</code> bezeichneten Namens.<br/>
                Die Wirkung entspricht <a href="#threadConstruction">Thread(null, null, name)</a>.
                 <br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#Thread(java.lang.String)"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="a">
                  <code>public Thread(<a href="#threadGroup">ThreadGroup</a> group, String name)</code>
               </sortcell>
               <cell>Erzeugt einen neuen Thread.<br/>
                Die Wirkung entspricht <a href="#threadConstruction">
                     <code>Thread(group, null, name)</code>
                  </a>,
                wobei <em>group</em> die Threadgruppe bezeichnet, innerhalb der der neu erzeugte Thread ablaufen soll.
                <code>name</code> bezeichnet den <a href="#threadName">Namen es neuen Threads</a>.<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#Thread(java.lang.ThreadGroup, java.lang.String)"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="a">
                  <code>public Thread(Runnable target, String name)</code>
               </sortcell>
               <cell>Erzeugt einen neuen Thread.<br/>
                Die Wirkung entspricht <a href="#threadConstruction">
                     <code>Thread(null, target, name)</code>
                  </a>,
                wobei <em>target</em> die nebenläufig auszuführende Klasse bezeichnet und <em>name</em> den <a href="#threadName">Namen des neuen Threads</a> festlegt.
                 <br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#Thread(java.lang.Runnable, java.lang.String)"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="a">
                  <code>
                     <a name="threadConstruction">public Thread(<a href="#threadGroup">ThreadGroup</a> group, <a href="#Runnable">Runnable</a>, String name)</a>
                  </code>
               </sortcell>
               <cell>Erzeugt einen neuen Thread.<br/>
                  <em>target</em> bezeichnet die nebenläufig auszuführende Klasse, welche zwingend die Schnittstelle <a href="#Runnable" keyword="yes">Runnable</a> implementiert.<br/>
                  <em>name</em> bezeichnet den <a href="#threadName">Namen des Threads</a>.<br/>
                  <em>group</em> bezeichnet im Falle der Existenz die Threadgruppe der der neue Thread zugeordnet werden soll. Ist diese <code>null</code> und ein <a fixedType="JDK14" offset="java/lang/SecurityManager.html" keyword="yes" external="yes">SecurityManager</a> existiert, so wird dessen Methode <a fixedType="JDK14" offset="java/lang/SecurityManager.html#getThreadGroup()">getThreadGroup</a> zur Ermittlung herangezogen. Existiert kein SecurityManager oder getThreadGroup liefert null, so wird der neu erzeugte Thread derselben Gruppe zugeordnet wie der erzeugende Thread.<br/>
Existiert ein SecurityManager so wird seine <a fixedType="JDK14" offset="java/lang/SecurityManager.html#checkAccess(java.lang.ThreadGroup)">checkAccess</a>-Methode aufgerufen um zu ermitteln, ob der Thread zur Erzeugungsoperation berechtigt ist. Ist er dies nicht, so wird ein Ausnahmeereignis des Typs <a fixedType="JDK14" offset="java/lang/SecurityException.html" external="yes" keyword="yes">SecurityException</a> erzeugt.<br/>
Ist das <em>target</em>-Argument ungleich <code>null</code>, so wird die Methode <a href="#run">
                     <code>run</code>
                  </a>-Methode des referenzierten Objektes zum Startzeitpunkt des Threads aufgerufen.<br/>
                  <a name="threadCreationPri">Die</a> Priorität eines neue erzeugten Threads entspricht der des erzeugenden Threads.<br/>
Handelt es sich beim erzeugenden Thread um einen Daemon-Thread, so wird der neu erzeugte auch <a href="#daemonAttr">als Daemon-Thread markiert</a>.
                        <br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#Thread(java.lang.ThreadGroup, java.lang.Runnable, java.lang.String)"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="setPriority">
                  <a name="setPriorityAPI" keyword="yes">public final void setPriority(int newPriority)</a>
               </sortcell>
               <cell>Legt die Priorität eines Threads fest.<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#setPriority(int)"/>
                  <br/>
                  <link href="#priorityEx">Codebeispiel</link>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="getPriority">
                  <a name="getPriorityAPI" keyword="yes">public final int intPriority()</a>
               </sortcell>
               <cell>Liefert die Priorität eines Threads.<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#getPriority()"/>
                  <br/>
                  <link href="#priorityEx">Codebeispiel</link>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="a">
                  <code>public Thread(<a href="#threadGroup">ThreadGroup</a> group, Runnable target, String name, long stackSize)</code>
               </sortcell>
               <cell>Erzeugt einen neuen Thread.<br/>
        Das Verhalten ist identisch zu <a href="#threadConstruction" keyword="yes">Thread(ThreadGroup,Runnable,String)</a>, mit Ausnahme der Möglichkeit die für den Thread zu reservierende Stackgröße durch den Parameter <em>stackSize</em> vorgeben zu können. Dieser Parameter kann genutzt werden um durch die Erhöhung des für den Programmfaden reservierten Speichers eine höhere Rekursionstiefe zu erreichen. Jedoch ist die Behandlung dieser Angabe im Konstruktor stark plattformabhängig und kann in verschiedenen Java-Implementierungen differieren!<br/>
        Die restlichen Parameter verhalten sich identisch zu <a href="#threadConstruction" keyword="yes">Thread(ThreadGroup,Runnable,String)</a>.<br/>
Diese Methode erzeugt innerhalb des Threadsystems eine Referenz auf jedes nebenläufig auszuführende Objekt (d.h. das durch den Parameter <em>target</em> referenzierte). Wird ein erzeugter Thread nicht durch <a href="#start" keyword="yes">start</a> gestartet und geeignet terminiert, so verbleibt das referenzierte Objekt dauerhaft im Speicher.
        <br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#Thread(java.lang.ThreadGroup, java.lang.Runnable, java.lang.String, long)"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="run">
                  <code>
                     <a name="run">public void run()</a>
                  </code>
               </sortcell>
               <cell>Wurde der Thread durch ein eigenständiges Objekt des Typs <code>Runnable</code> erzeugt, so kann er durch expliziten Aufruf dieser Methode gestartet werden.<br/>
        Konzeptionell bildetet die Methode <code>run</code> die main-Methode eines Threads.<br/>
        Üblicherweise überschreiben von <code>Thread</code> abgeleitete Klassen diese Methode.
          <br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#run()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="exit">
                  <code>private void exit()</code>
               </sortcell>
               <cell>Wird durch das Laufzeitsystem automatisch bei Terminierung eines Threads aufgerufen.<br/>
        Konzeptionell bildet diese Methode das Analogon des Destruktors für Klassen.<br/>
        Seit JDK 1.1 wird innerhalb dieser Methode dem durch den Thread ausgeführten Objekt explizit <code>null</code> zugewiesen um seine Entfernung durch den Garbage Collector sicherzustellen. (<a href="http://developer.java.sun.com/developer/bugParade/bugs/4006245.html">siehe Java Bug 4006245</a>)</cell>
            </row>
            <row>
               <sortcell sortCrit="stop">
                  <code>
                     <a name="stop">public final void stop()</a>
                  </code>
               </sortcell>
               <cell>Beendet einen in Ausführung befindlichen Thread unverzüglich unter Freigabe der durch ihn gehaltenen Sperren.<br/>
Diese Methode ist durch SUN als <em>deprecated</em> gekennzeichnet und sollte nicht mehr verwendet werden. Sie gibt gesperrte Objekte auch dann frei, wenn sie sich dadurch in einem inkonsistenten Zustand befinden. (<a href="http://java.sun.com/j2se/1.4/docs/guide/misc/threadPrimitiveDeprecation.html" external="yes">Weitere Informationen dazu</a>)<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#stop()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="stop">
                  <code>public final synchronized void stop(<a fixedType="JDK14" offset="java/lang/Throwable.html" external="yes">Throwable</a> obj)</code>
               </sortcell>
               <cell>Beendet einen in Ausführung befindlichen Thread unverzüglich unter Freigabe der durch ihn gehaltenen Sperren.<br/>
Auch diese Methode ist (genauso wie <a href="#stop">
                     <code>stop</code>
                  </a>) als deprecated markiert und sollte nicht mehr verwendet werden. Zusätzlich zu den bei <a href="#stop">
                     <code>stop</code>
                  </a> gegebenen Anmerkungen tritt bei ihrer Verwendung die Gefahr auf, daß durch <em>obj</em> ein Ausnahmeereignisobjekt im Stack plaziert wird, für dessen Verarbeitung der empfangende Thread nicht präpariert wurde.<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#stop(java.lang.Throwable)"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="interrupt">
                  <code>
                     <a name="interrupt">public void interrupt()</a>
                  </code>
               </sortcell>
               <cell>Unterbricht den laufenden Thread und setzt sein Unterbrechungsflag.<br/>
        Zunächst wird durch Aufruf der Methode <a href="#checkAccess">
                     <code>checkAccess</code>
                  </a> geprüft ob der Thread zur Unterbrechung anderen Programmfadens berechtigt ist. Ist dies nicht der Fall, so wird ein <a fixedType="JDK14" offset="java/lang/SecurityException.html">
                     <code>SecurityException</code>
                  </a>-Ausnahmeereignis erzeugt. Fall der zu unterbrechende Thread sich im <a href="#stateBlocked">Zustand <em>blockiert</em>
                  </a> befindet, wird ein <a fixedType="JDK14" offset="java/lang/InterruptedException.html">
                     <code>InterruptedException</code>
                  </a>-Ausnahmeereignis erzeugt.<br/>
Wurde der zu unterbrechende Thread durch eine E/A-Operation auf einem <a fixedType="JDK14" offset="java/nio/channels/InterruptibleChannel.html">
                     <em>unterbrechbaren Kanal</em>
                  </a> blockiert, so verliert er den Kanal und sein Unterbrechungsflag wird gesetzt. Zusätzlich empfängt er ein <a fixedType="JDK14" offset="java/nio/channels/ClosedByInterruptException.html">
                     <code>ClosedByInterruptException</code>
                  </a>-Ausnahmeereignis.<br/>
Sollte sich der zu unterbrechende Thread innerhalb eines <a fixedType="JDK14" offset="java/nio/channels/Selector.html" external="yes" keyword="yes">Selector</a>-Objekts blockiert finden, so kehrt er unverzüglich (evtl. auch mit leerer Rückgabe) zurück. (Dieses Verhalten ist Äquivalent zum Aufruf der Methode <a fixedType="JDK14" offset="java/nio/channels/Selector.html#wakeup()" external="yes" keyword="yes">wakeup</a> auf einem <code>Selector</code>-Objekt.)<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#interrupt()"/>
                  <br/>
                  <link href="#MissedNotifyline21">Codebeispiel</link>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="interrupted">
                  <code>
                     <a name="interrupted">public static boolean interrupted()</a>
                  </code>
               </sortcell>
               <cell>Liest das Unterbrechungsflag aus und setzt es zurück.<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#interrupted()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="isInterrupted">
                  <code>
                     <a name="isInterrupted">public boolean isInterrupted()</a>
                  </code>
               </sortcell>
               <cell>Liest das Unterbrechungsflag aus.<br/>
        Diese Methode setzt das Flag jedoch nach dem Lesevorgang -- im Gegensatz zu <a href="#interrupted" keyword="yes">interrupted</a> -- nicht zurück.<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#isInterrupted()"/>
                  <br/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="isInterrupted1">
                  <code>private native boolean isInterrupted(boolean ClearInterrupted)</code>
               </sortcell>
               <cell>Liest das Unterbrechungsflag eines Threads aus und setzt es in Abhängigkeit von <em>ClearInterrupted</em> zurück.<br/>
        Diese Methode wird durch <a href="#interrupted" keyword="yes">interrupted</a> und <a href="#isInterrupted" keyword="yes">isInterrupted</a> intern aufgerufen.
        </cell>
            </row>
            <row>
               <sortcell sortCrit="destroy">
                  <code>public void destroy()</code>
               </sortcell>
               <cell>Zerstört einen Thread augenblicklich, ohne durch ihn gesetzte Sperren freizugeben.<br/>
        Diese Methode ist nicht implementiert und führt beim Aufruf zu einem Ausnahmeereignis des Typs <a fixedType="JDK14" offset="java/lang/NoSuchMethodError.html" external="yes" keyword="yes">NoSuchMethodError</a>.<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#destroy()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="isAlive">
                  <code>public final native boolean isAlive()</code>
               </sortcell>
               <cell>Testet ob sich ein Thread im Zustand <em>alive</em> befindet, d.h. ob er gestartet und noch nicht beendet wurde.<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#isAlive()"/>
                  <br/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="suspend">
                  <code>
                     <a name="suspend">public final void suspend()</a>
                  </code>
               </sortcell>
               <cell>Unterbricht die Ausführung eines Threads.<br/>
        Diese Methode ist als <em>deprecated</em> gekennzeichnet und sollte daher nicht mehr verwendet werden,
        da sie kann im Zusammenhang mit Sperren zu unauflösbaren Verklemmungen führen kann. (<a href="http://java.sun.com/j2se/1.4/docs/guide/misc/threadPrimitiveDeprecation.html" external="yes">Weitere Informationen dazu</a>)<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#suspend()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="resume">
                  <code>public final void resume()</code>
               </sortcell>
               <cell>Überführt einen zuvor durch <a href="#suspend" keyword="yes">suspend</a> unterbrochenen Thread wieder in den <a href="#stateAlive">Zustand <em>alive</em>
                  </a>.<br/>
        Diese Methode ist als <em>deprecated</em> gekennzeichnet und sollte daher nicht mehr verwendet werden,
        da sie kann im Zusammenhang mit Sperren zu unauflösbaren Verklemmungen führen kann. (<a href="http://java.sun.com/j2se/1.4/docs/guide/misc/threadPrimitiveDeprecation.html" external="yes">Weitere Informationen dazu</a>)<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#resume()"/>
                  <br/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="setName">
                  <code>public final void setName(String name)</code>
               </sortcell>
               <cell>Setzt den Namen eines Threads.<br/>
        Die Berechtigung zur Namensänderung wird durch Aufruf der Methode <a href="#checkAccess" keyword="yes">checkAccess</a> geprüft. Liegt sie nicht vor, so wird ein <a fixedType="JDK14" offset="java/lang/SecurityException.html" keyword="yes" external="yes">SecurityException</a>-Ausnahmeereignis erzeugt.<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#setName(java.lang.String)"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="getName">
                  <code>public final String getName</code>
               </sortcell>
               <cell>Liefert den Namen des Threads zurück.<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#getName()"/>
                  <br/>
                  <link href="#concurrentIncrementline45">Codebeispiel</link>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="getThreadGroup">
                  <code>public final <a href="#threadGroup">ThreadGroup</a> getThreadGroup()</code>
               </sortcell>
               <cell>Liefert die Threadgruppe zurück, welcher der Thread zugeordnet ist.<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#getThreadGroup()"/>
                  <br/>
                  <link href="#priorityExline8">Codebeispiel</link>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="activeCount">
                  <code>public static int activeCount()</code>
               </sortcell>
               <cell>Liefert die Anzahl der aktiven Threads innerhalb der Threadgruppe zurück, der der aktuelle Thread angehört.<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#activeCount()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="enumerate">
                  <code>public static int enumerate(Thread[] tarray)</code>
               </sortcell>
               <cell>Kopiert Verweise auf alle Programmfäden die sich in derselben Gruppe, oder einer ihrer Untergruppen, wie der aktuelle Thread befinden in den Array <em>tarray</em>.<br/>
        Zuvor wird durch Aufruf der Methode <a href="#checkAccess" keyword="yes">checkAccess</a> geprüft, ob er anfragende Thread zu dieser Operation berechtigt ist. Ist dies nicht der Fall, so wird ein <a fixedType="JDK14" offset="java/lang/SecurityException.html" keyword="yes" external="yes">SecurityException</a>-Ausnahmeereignis erzeugt.<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#enumerate(java.lang.Thread[])"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="countStackFrame">
                  <code>public native int countStackFrames()</code>
               </sortcell>
               <cell>Gibt die Anzahl der Stackframes eines zuvor unterbrochenen Threads zurück.<br/>
        Diese Methode ist als <em>deprecated</em> gekennzeichnet und sollte daher nicht mehr verwendet werden!<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#countStackFrames()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="join">
                  <code>
                     <a name="join">public final synchronized void join(long millis)</a>
                  </code>
               </sortcell>
               <cell>Wartet höchstens <em>millis</em> Millisekunden auf die Beendigung eines anderen Threads.<br/>
        Ein Wert von 0 erlaubt unbegrenztes Warten. Wartezeiten &lt;0 ziehen eine <a fixedType="JDK14" offset="java/lang/IllegalArgumentException.html" keyword="yes" external="yes">IllegalArgumentException</a> nach sich.<br/>
        Während der Wartezeit wird der wartende Thread blockiert. Wird er während diesem Zeitraum unterbrochen, so wird ein <a fixedType="JDK14" offset="java/lang/InterruptedException.html" keyword="yes" external="yes">InterruptedException</a>-Ausnahmeereignis erzeugt.<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#join(long)"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="join1">
                  <code>public final synchronized void join(long millis, int nanos)</code>
               </sortcell>
               <cell>Wartet die in Millisekunden (<em>millis</em>) und Nannosekungen (<em>nanos</em>) festgelegte Zeitspanne auf das Beenden eines Threads.<br/>
        De facto wird das <em>nanos</em>-Argument bei <em>millis</em>&gt;0 für Werte kleiner 500000 ignoriert. Andernfalls (d.h. <em>millis</em>=0) wird genau eine Millisekunde gewartet. In beiden Fällen wird der Aufruf auf <a href="#join" keyword="yes">join</a> abgebildet.<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#join(long, int)"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="join2">
                  <code>public final void join()</code>
               </sortcell>
               <cell>Wartet beliebig lange auf das Beenden einen Threads.<br/>
        Der Aufruf ist äquivalent zur <a href="#join" keyword="yes">join(0)</a>.<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#join()"/>
                  <br/>
                  <link href="#concurrentIncrementline27">Codebeispiel</link>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="dumpStack">
                  <code>public static void dumpStack()</code>
               </sortcell>
               <cell>Gibt den Stacktrace des aktuellen Threads aus.<br/>
        Diese Methode ist lediglich zur Fehlersuche sinnvoll einsetzbar.<br/>
        Intern wird zur Ausgabe des aktuellen Stackinhaltes ein Ausnahmeereignisobjekt des Typs <a fixedType="JDK14" offset="java/lang/Exception.html" keyword="yes" external="yes">Exception</a> erzeugt.<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#dumpStack()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="checkAccess">
                  <code>
                     <a name="checkAccess">public final void checkAccess()</a>
                  </code>
               </sortcell>
               <cell>Prüft ob der aktuelle Thread zur Änderung der Threadeigenschaften berechtigt ist.<br/>
        Zur Durchführung der Prüfung muß ein <a fixedType="JDK14" offset="java/lang/SecurityManager.html" keyword="yes" external="yes">SecurityManager</a> im System existieren.<br/>
        Liegt die Berechtigung zur Modifikation für den anfragenden Thread nicht vor, so wird ein <a fixedType="JDK14" offset="java/lang/SecurityException.html" keyword="yes" external="yes">SecurityException</a>-Ausnahmeereignis erzeugt.<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#checkAccess()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="toString">
                  <code>public String toString()</code>
               </sortcell>
               <cell>Liefert eine Stringrepräsentation des Threads zurück.<br/>
        Die erzeugte Zeichenkettendarstellung ist der Form:<br/>
                  <b>Thread[<em>Threadname</em>,<em>Priorität</em>,<em>Name der Threadgruppe</em>]</b>,<br/>
        wobei die Gruppenangabe fehlen kann.<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#toString()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="holdsLock">
                  <code>public static native boolean holdsLock(<a fixedType="JDK14" offset="java/lang/Object.html" external="yes">Object</a> obj)</code>
               </sortcell>
               <cell>Liefert <em>true</em> falls der Thread eine Sperre auf das Objekt <em>obj</em> hält.<br/>
                  <seeapi ver="1.4" offset="java/lang/Thread.html#holdsLock(java.lang.Object)"/>
               </cell>
            </row>
         </body>
      </tabular>
      <keyword alt="Schnittstelle Runnable">
         <subtopic name="Runnable">Die Schnittstelle <code>Runnable</code>
         </subtopic>
      </keyword>
      <p>Die <a fixedType="JDK14" offset="java/lang/Runnable.html" external="yes">Schnittstelle <code>Runnable</code>
         </a> befindet sich im Paket <a fixedType="JDK14" offset="java/lang/package-frame.html" keyword="yes" external="yes">java.lang</a>.<br/>
         <link href="examples/sunSrc/Runnable.java">Quellcode der Schnittstelle <code>Runnable</code>
         </link>
         <br/>
Die Schnittstelle wird durch die Klasse <a href="#classThread" keyword="yes">Thread</a> standardmäßig implementiert, weshalb zur nebenläufigen Ausführung einer beliebigen Klasse das Erben von <code>Thread</code> genügt.<br/>
In vielen praktischen Fällen ist dies jedoch nicht gewünscht, da hierdurch eine mit unter ungewollte Typisierung entsteht, oder nicht möglich, etwa weil bereits eine Superklasse existiert, in diesen Fällen wird auf die Implementierung der Schnittstelle <code>Runnable</code> zurückgegriffen.</p>
      <tabular summary="Operationen der Schnittstelle Runnable in Java 1.4">
         <head length="2">
            <column title="Operation"/>
            <column title="Semantik"/>
         </head>
         <body>
            <row>
               <cell>
                  <code>public abstract void run()</code>
               </cell>
               <cell>Diese Methode wird durch Aufruf der <a href="#start" keyword="yes">start</a>-Methode auf einem <code>Thread</code>-Objekt (oder einer Subklasse davon) ausgeführt.<br/>
                Konzeptionell entspricht sie einer main-Methode für einen Thread.<br/>
                  <seeapi ver="1.4" offset="java/lang/Runnable.html#run()"/>
                  <br/>
                  <link href="#interfaceBasedline26">Codebeispiel</link>
               </cell>
            </row>
         </body>
      </tabular>
      <keyword alt="Klasse ThreadGroup">
         <subtopic name="threadGroup">Die Klasse <code>ThreadGroup</code>
         </subtopic>
      </keyword>
      <p>Die <a fixedType="JDK14" offset="java/lang/ThreadGroup.html" external="yes">Klasse <code>ThreadGroup</code>
         </a> befindet sich im Paket <a fixedType="JDK14" offset="java/lang/package-frame.html" keyword="yes" external="yes">java.lang</a>.<br/>
    Sie gestattet es Threads wahlfrei zu gruppieren und zu strukturieren.<br/>
    Überdies erlaubt sie es threadspezifische Operationen gesammelt auf einer Gruppe von Threads auszuführen.<br/>
         <link href="examples/sunSrc/ThreadGroup.java">Quellcode der Klasse <code>ThreadGroup</code>
         </link>
         <br/>
      </p>
      <tabular summary="Attribute der Klasse ThreadGroup in Java 1.4">
         <head length="2">
            <column title="Attribut"/>
            <column title="Semantik"/>
         </head>
         <body>
            <row>
               <sortcell sortCrit="parent">
                  <code>ThreadGroup parent</code>
               </sortcell>
               <cell>Verweis auf die Elternthreadgruppe, d.h. die Threadgruppe welche die aktuelle beinhaltet.</cell>
            </row>
            <row>
               <sortcell sortCrit="name">
                  <code>String name</code>
               </sortcell>
               <cell>Name der Threadgruppe.</cell>
            </row>
            <row>
               <sortcell sortCrit="maxPriority">
                  <code>
                     <a name="maxPriority">int maxPriority</a>
                  </code>
               </sortcell>
               <cell>Enthält die höchstmögliche Priorität eines Threads innerhalb der Threadgruppe.<br/>
                Standardmäßig wird die Variable während des Initialisierungsvorganges mit dem Wert der Konstanten <a href="#maxPri" keyword="yes">MAX_PRIORITY</a> belegt.</cell>
            </row>
            <row>
               <sortcell sortCrit="daemon">
                  <code>boolean daemon</code>
               </sortcell>
               <cell>
                  <code>true</code> falls es sich bei der Threadgruppe um eine Daemonthreadgruppe handelt.</cell>
            </row>
            <row>
               <sortcell sortCrit="vmAllowSuspension">
                  <code>boolean vmAllowSuspension</code>
               </sortcell>
               <cell>Boole'scher Wert, der angab (inzwischen wird er nicht mehr verwendet) ob im Falle knappen Speichers Threads angehalten werden dürfen.</cell>
            </row>
            <row>
               <sortcell sortCrit="nthreads">
                  <code>int nthreads</code>
               </sortcell>
               <cell>Anzahl der Threads einer Threadgruppe.</cell>
            </row>
            <row>
               <sortcell sortCrit="threads">
                  <code>Thread threads[]</code>
               </sortcell>
               <cell>Liste mit Verweisen auf die Threads innerhalb der Threadgruppe.</cell>
            </row>
            <row>
               <sortcell sortCrit="ngroups">
                  <code>int ngroups</code>
               </sortcell>
               <cell>Anzahl der Threadgruppen innerhalb einer Threadgruppe.</cell>
            </row>
            <row>
               <sortcell sortCrit="groups">
                  <code>ThreadGroup groups[]</code>
               </sortcell>
               <cell>Liste mit Verweisen auf die Threadgruppen innerhalb einer Threadgruppe.</cell>
            </row>
         </body>
      </tabular>
      <tabular summary="Operationen der Klasse ThreadGroup in Java 1.4">
         <head length="2">
            <column title="Operation"/>
            <column title="Semantik"/>
         </head>
         <body>
            <row>
               <sortcell sortCrit="a1">
                  <code>private <a href="#threadGroup">ThreadGroup</a>()</code>
               </sortcell>
               <cell>Erzeugt eine Threadgruppe.<br/>
                Dieser Konstruktor wird durch eine native C-Methode aufgerufen um die <code>system</code>-Threadgruppe zu erzeugen.<br/>
Auch die Initialisierung der Variable <a href="#maxPriority" keyword="yes">maxPriority</a> erfolgt in dieser Methode.
                </cell>
            </row>
            <row>
               <sortcell sortCrit="a2">
                  <code>public ThreadGroup(String name)</code>
               </sortcell>
               <cell>Erzeugt eine neue Threadgruppe als Kindgruppe der Gruppe welcher der aktuell ausgeführte Thread zugeordnet ist.<br/>
                Durch Aufruf der Methode <a href="#checkAccess" keyword="yes">checkAccess</a> auf der Threadgruppe des aktuellen Threads wird geprüft ob dieser zur Gruppenerzeugung berechtigt ist.
                Ist dies nicht der Fall, so wird ein <a fixedType="JDK14" offset="java/lang/SecurityException.html" keyword="yes">SecurityException</a>-Ausnahmeereignis erzeugt.
                <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#ThreadGroup(java.lang.String)"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="a3">
                  <code>public ThreadGroup(<a href="#threadGroup">ThreadGroup</a> parent, String name)</code>
               </sortcell>
               <cell>Erzeugt eine neue Threadgruppe unter dem Namen <em>name</em> und ordnet diese der Gruppe <em>parent</em> als Kindgruppe zu.<br/>
                Durch Aufruf der Methode <a href="#checkAccess" keyword="yes">checkAccess</a> auf der Threadgruppe des aktuellen Threads wird geprüft ob dieser zur Gruppenerzeugung berechtigt ist.
                Ist dies nicht der Fall, so wird ein <a fixedType="JDK14" offset="java/lang/SecurityException.html" keyword="yes">SecurityException</a>-Ausnahmeereignis erzeugt.<br/>
                Existiert die Elternthreadgruppe nicht (oder die Referenz hat den Wert <code>null</code>), so wird ein <a fixedType="JDK14" offset="java/lang/NullPointerException.html" keyword="yes">NullPointerException</a>-Ausnahmeereignis erzeugt.
                <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#ThreadGroup(java.lang.ThreadGroup, java.lang.String)"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="getName">
                  <code>public final String getName()</code>
               </sortcell>
               <cell>Liefert den Namen der Threadgruppe.<br/>
                Zumindest die vordefinierten Threadgruppen <code>system</code> und <code>main</code> existieren immer im System, wobei <code>main</code> als Subgruppe von <code>system</code> organisiert ist.
                <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#getName()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="getParent">
                  <code>public final <a href="#threadGroup">ThreadGroup</a> getParent()</code>
               </sortcell>
               <cell>Liefert im Falle der Existenz einen Verweis auf die Elternthreadgruppe.<br/>
                Zumindest die vordefinierten Threadgruppen <code>system</code> und <code>main</code> existieren immer im System, wobei <code>main</code> als Subgruppe von <code>system</code> organisiert ist.
                <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#getParent()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="getMaxPriority">
                  <code>public final int getMaxPriority()</code>
               </sortcell>
               <cell>Liefert die maximal für Threads der Gruppe festlegbare Priorität zurück.
                <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#getMaxPriority()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="isDaemon">
                  <code>public final boolean isDaemon()</code>
               </sortcell>
               <cell>Testet ob es sich um eine Daemon-Threadgruppe handelt.<br/>
                Eine solche Gruppe wird automatisch nach Terminierung des letzten enthaltenen Threads oder der letzten enthaltenen Threadgruppe zerstört.
                <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#isDaemon()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="isDestroyed">
                  <code>public synchronized boolean isDestroyed()</code>
               </sortcell>
               <cell>Testet ob die Threadgruppe zerstört wurde.
                <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#isDestroyed()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="setDaemon">
                  <a href="#setDaemonAPI" keyword="yes">public final void setDaemon(boolean daemon)</a>
               </sortcell>
               <cell>Setzt den Daemonzustand einer Threadgruppe.<br/>
                Die Berechtigung zu dieser Operation wird durch Aufruf der <a href="#checkAccessTG" keyword="yes">checkAccess</a>-Methode auf der zu modifizierenden Threadgruppe geprüft.
                Liegt diese nicht vor, so wird ein <a fixedType="JDK14" offset="java/lang/SecurityException.html" keyword="yes">SecurityException</a>-Ausnahmeereignis erzeugt.<br/>
                Wird diese Methode während der Ausführungszeit eines Threads aufgerufen, so wird einej <a fixedType="JDK14" offset="java/lang/IllegalThreadStateException.html" keyword="yes">IllegalThreadStateException</a>-Ausnahme erzeugt.
                <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#setDaemon(boolean)"/>
                  <br/>
                  <link href="#bakerySimulation2line10">Codebeispiel</link>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="setMaxPriority">
                  <code>public final void setMaxPriority(int pri)</code>
               </sortcell>
               <cell>Setzt die Prioritätsoberschranke einer Threadgruppe.<br/>
                Der Wer von <em>pri</em> muß sich zwischen <a href="#minPri" keyword="yes">MIN_PRIORITY</a> und <a href="#maxPri" keyword="yes">MAX_PRIORITY</a> bewegen, andernfalls wird der Aufruf folgenlos ignoriert.<br/>
                Zusätzlich muß übergebene Wert unterhalb der Prioritätsschranke des Elternthreadgruppe liegen. Um die rekursive Anwendbarkeit dieser Festlegung sicherzustellen, wird die <code>system</code>-Threadgruppe mit der Priorität <a href="#maxPri" keyword="yes">MAX_PRIORITY</a> belegt.
                <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#setMaxPriority(int)"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="parentOf">
                  <code>public final boolean parentOf(<a href="#threadGroup">ThreadGroup</a> g)</code>
               </sortcell>
               <cell>Testet ob die als <em>g</em> übergebene Threadgruppe gleich dem Threadgruppen-Objekt ist auf dem die Methode ausgeführt wird, oder eine der Vorfahren-Threadgruppen.
                <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#parentOf(java.lang.ThreadGroup)"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="checkAccess">
                  <code>
                     <a name="checkAccessTG">public final void checkAccess()</a>
                  </code>
               </sortcell>
               <cell>Prüft ob der aktuell ausgeführte Thread die Berechtigung zur Veränderung der Threadgruppencharakteristika besitzt.<br/>
                Zur Ermittlung der Berechtigung wird die <code>checkAccess</code>-Methode des <a fixedType="JDK14" offset="java/lang/SecurityManager.html" keyword="yes" external="yes">SecurityManager</a>s aufgerufen.
                Liegt keine Berechtigung vor, so wird ein <a fixedType="JDK14" offset="java/lang/SecurityException.html" keyword="yes" external="yes">SecurityException</a>-Ausnahmeereignis erzeugt.
                <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#checkAccess()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="activeCount">
                  <code>
                     <a name="activeCount">public int activeCount()</a>
                  </code>
               </sortcell>
               <cell>Liefert einen Schätzwert der aktuell aktiven Threads innerhalb einer Threadgruppe zurück.<br/>
                Der Zählvorgang beeinflußt die Lebenszyklen der Threads im System nicht, daher kann das Ergebnis von der Anzahl der dann tatsächlich existierenden Programmfäden abweichen.
                <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#activeCount()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="enumerate">
                  <code>public int enumerate(<a href="#classThread">Thread</a> list[])</code>
               </sortcell>
               <cell>Kopiert rekursiv alle aktiven Threads der aktuellen Gruppe und deren Kindgruppen in den übergebenen Array.<br/>
                Vor Ausführung der Kopieroperation wird die Berechtigung mittels des Aufrufs von <a href="#checkAccessTG" keyword="yes">checkAccess</a> auf der Threadgruppe geprüft. Liegt keine hinreichende Berechtigung vor, so wird ein <a fixedType="JDK14" offset="java/lang/SecurityException.html" keyword="yes" external="yes">SecurityException</a>-Ausnahmeereignis erzeugt.<br/>
                Zur Ermittlung der notwendigen Arraygröße sollte die Methode <a href="#activeCount" keyword="yes">activeCount</a> genutzt werden.
                Andernfalls werden diejenigen Threads, welche aufgrund der Großenbeschränkung nicht mehr in den Array aufgenommen werden können stillschweigend ignoriert.
                <br/>Der Aufruf entspricht <a href="#enumerate" keyword="yes">enumerate(list, 0, true)</a>.
                <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#enumerate(java.lang.Thread[])"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="enumerate1">
                  <code>public int enumerate(<a href="#classThread">Thread</a> list[], boolean recurse)</code>
               </sortcell>
               <cell>Kopiert alle aktiven Threads der aktuellen Gruppe in den übergebenen Array.<br/>
                Ist Parameter <em>recurse</em> mit <code>true</code> belegt, so wird dieser Vorgang rekursiv auch für die Kindthreadgruppen durchgeführt.<br/>
                Vor Ausführung der Kopieroperation wird die Berechtigung mittels des Aufrufs von <a href="#checkAccessTG" keyword="yes">checkAccess</a> auf der Threadgruppe geprüft. Liegt keine hinreichende Berechtigung vor, so wird ein <a fixedType="JDK14" offset="java/lang/SecurityException.html" keyword="yes" external="yes">SecurityException</a>-Ausnahmeereignis erzeugt.<br/>
                Zur Ermittlung der notwendigen Arraygröße sollte die Methode <a href="#activeCount" keyword="yes">activeCount</a> genutzt werden.
                Andernfalls werden diejenigen Threads, welche aufgrund der Großenbeschränkung nicht mehr in den Array aufgenommen werden können stillschweigend ignoriert.
                <br/>Der Aufruf entspricht <a href="#enumerate" keyword="yes">enumerate(list, 0, recurse)</a>.

                <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#enumerate(java.lang.Thread[], boolean)"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="enumerate2">
                  <code>
                     <a name="enumerate">private int enumerate(<a href="#classThread">Thread</a> list[], int n, boolean recurse)</a>
                  </code>
               </sortcell>
               <cell>Kopiert alle, bis auf <em>n</em> Threads der aktuellen Gruppe in den übergebenen Array.<br/>
                Ist Parameter <em>recurse</em> mit <code>true</code> belegt, so wird dieser Vorgang rekursiv auch für die Kindthreadgruppen durchgeführt.<br/>
                Vor Ausführung der Kopieroperation wird die Berechtigung mittels des Aufrufs von <a href="#checkAccessTG" keyword="yes">checkAccess</a> auf der Threadgruppe geprüft. Liegt keine hinreichende Berechtigung vor, so wird ein <a fixedType="JDK14" offset="java/lang/SecurityException.html" keyword="yes" external="yes">SecurityException</a>-Ausnahmeereignis erzeugt.<br/>
                Zur Ermittlung der notwendigen Arraygröße sollte die Methode <a href="#activeCount" keyword="yes">activeCount</a> genutzt werden.
                </cell>
            </row>
            <row>
               <sortcell sortCrit="activeGroupCount">
                  <code>
                     <a name="activeGroupCount">public int activeGroupCount()</a>
                  </code>
               </sortcell>
               <cell>Liefert einen Schätzwert der aktuell aktiven Threadgruppen innerhalb eines Threads.
                Der Zählvorgang beeinflußt die Lebenszyklen der Threadgruppen im System nicht, daher kann das Ergebnis von der Anzahl der dann tatsächlich existierenden Gruppen abweichen.
                <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#activeGroupCount()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="enumerate4">
                  <code>public int enumerate(<a href="#threadGroup">ThreadGroup</a> list[])</code>
               </sortcell>
               <cell>Kopiert rekursiv alle aktiven Threadgruppen und deren Kindgruppen in den übergebenen Array.<br/>
                Vor Ausführung der Kopieroperation wird die Berechtigung mittels des Aufrufs von <a href="#checkAccessTG" keyword="yes">checkAccess</a> auf der Threadgruppe geprüft. Liegt keine hinreichende Berechtigung vor, so wird ein <a fixedType="JDK14" offset="java/lang/SecurityException.html" keyword="yes" external="yes">SecurityException</a>-Ausnahmeereignis erzeugt.<br/>
                Zur Ermittlung der notwendigen Arraygröße sollte die Methode <a href="#activeGroupCount" keyword="yes">activeGroupCount</a> genutzt werden.
                Andernfalls werden diejenigen Threadgruppen, welche aufgrund der Großenbeschränkung nicht mehr in den Array aufgenommen werden können stillschweigend ignoriert.
                <br/>Der Aufruf entspricht <a href="#enumerateTG" keyword="yes">enumerate(list, 0, true)</a>.
                <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#enumerate(java.lang.ThreadGroup[])"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="enumerate5">
                  <code>public int enumerate(<a href="#threadGroup">ThreadGroup</a> list[], boolean recurse)</code>
               </sortcell>
               <cell>Kopiert alle aktiven Threadgruppen in den übergebenen Array.<br/>
                Ist Parameter <em>recurse</em> mit <code>true</code> belegt, so wird dieser Vorgang rekursiv auch für die Kindthreadgruppen durchgeführt.<br/>
                Vor Ausführung der Kopieroperation wird die Berechtigung mittels des Aufrufs von <a href="#checkAccessTG" keyword="yes">checkAccess</a> auf der Threadgruppe geprüft. Liegt keine hinreichende Berechtigung vor, so wird ein <a fixedType="JDK14" offset="java/lang/SecurityException.html" keyword="yes" external="yes">SecurityException</a>-Ausnahmeereignis erzeugt.<br/>
                Zur Ermittlung der notwendigen Arraygröße sollte die Methode <a href="#activeGroupCount" keyword="yes">activeGroupCount</a> genutzt werden.
                Andernfalls werden diejenigen Threadgruppen, welche aufgrund der Großenbeschränkung nicht mehr in den Array aufgenommen werden können stillschweigend ignoriert.
                <br/>Der Aufruf entspricht <a href="#enumerateTG" keyword="yes">enumerate(list, 0, recurse)</a>.
                <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#enumerate(java.lang.ThreadGroup[], boolean)"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="enumerate6">
                  <code>
                     <a name="enumerateTG">private int enumerate(<a href="#threadGroup">ThreadGroup</a> list[], int n, boolean recurse)</a>
                  </code>
               </sortcell>
               <cell>Kopiert alle, bis auf <em>n</em> Threadgruppen in den übergebenen Array.<br/>
                Ist Parameter <em>recurse</em> mit <code>true</code> belegt, so wird dieser Vorgang rekursiv auch für die Kindthreadgruppen durchgeführt.<br/>
                Vor Ausführung der Kopieroperation wird die Berechtigung mittels des Aufrufs von <a href="#checkAccessTG" keyword="yes">checkAccess</a> auf der Threadgruppe geprüft. Liegt keine hinreichende Berechtigung vor, so wird ein <a fixedType="JDK14" offset="java/lang/SecurityException.html" keyword="yes" external="yes">SecurityException</a>-Ausnahmeereignis erzeugt.<br/>
                Zur Ermittlung der notwendigen Arraygröße sollte die Methode <a href="#activeGroupCount" keyword="yes">activeGroupCount</a> genutzt werden.
                </cell>
            </row>
            <row>
               <sortcell sortCrit="stop">
                  <code>
                     <a name="stopTG">public final void stop()</a>
                  </code>
               </sortcell>
               <cell>Beendet alle Threads der Gruppe.<br/>
                Diese Methode ist als <em>deprecated</em> gekennzeichnet und sollte nicht mehr verwendet werden!<br/>
                Da die Implementierung den Aufruf elementweise auf die <a href="#stop" keyword="yes">stop</a>-Methode der Klasse <code>Thread</code> abbildet, wirken die dort skizzierten Probleme hier fort.
                <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#stop()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="interrupt">
                  <code>public final void interrupt()</code>
               </sortcell>
               <cell>Unterbricht alle Threads der Gruppe.<br/>
                Diese Methode ist als <em>deprecated</em> gekennzeichnet und sollte nicht mehr verwendet werden!<br/>
                Da die Implementierung den Aufruf elementweise auf die <a href="#interrupt" keyword="yes">interrupt</a>-Methode der Klasse <code>Thread</code> abbildet, wirken die dort skizzierten Probleme hier fort.
                <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#interrupt()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="suspend">
                  <code>
                     <a name="suspendTG">public final void suspend()</a>
                  </code>
               </sortcell>
               <cell>Brockiert alle Threads der Gruppe.<br/>
                Diese Methode ist als <em>deprecated</em> gekennzeichnet und sollte nicht mehr verwendet werden!<br/>
                Da die Implementierung den Aufruf elementweise auf die <a href="#suspend" keyword="yes">suspend</a>-Methode der Klasse <code>Thread</code> abbildet, wirken die dort skizzierten Probleme hier fort.
                <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#suspend()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="stopOrSuspend">
                  <code>private boolean stopOrSuspend(boolean suspend)</code>
               </sortcell>
               <cell>Hilfsmethode die durch <a href="#stopTG" keyword="yes">stop</a> und <a href="#suspendTG" keyword="yes">suspend</a> verwendet wird.                </cell>
            </row>
            <row>
               <sortcell sortCrit="resume">
                  <code>public final void resume()</code>
               </sortcell>
               <cell>Nimmt die Verarbeitung für alle zuvor blockierten oder unterbrochenen Threads der Gruppe wieder auf.<br/>
                Diese Methode wird ausschließlich im Zusammenspiel mit <a href="#suspendTG" keyword="yes">suspend</a> und <a href="#interruptTG" keyword="yes">interrupt</a> verwendet, die beide als <em>deprecated</em> markiert sind und daher nicht mehr verwendet werden sollten.
                <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#resume()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="destroy">
                  <code>public final void destroy()</code>
               </sortcell>
               <cell>Zerstört die Threadgruppe einschließlich der darin enthaltenen Kindgruppen.<br/>
                Die Gruppen dürfen keine Threads mehr enthalten, andernfalls wird ein <a fixedType="JDK14" offset="java/lang/IllegalThreadStateException.html" keyword="yes" external="yes">IllegalThreadStateException</a>-Ausnahmeereignis erzeugt.<br/>
                Ist der ausführende Thread nicht zur Operation berechtigt, so wird ein <a fixedType="JDK14" offset="java/lang/SecurityException.html" keyword="yes" external="yes">SecurityException</a>-Ausnahmeereignis erzeugt.
                <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#destroy()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="add">
                  <code>private final void add(<a href="#threadGroup">ThreadGroup</a> g)</code>
               </sortcell>
               <cell>Fügt der aktuellen Threadgruppe die Threadgruppe <em>g</em> hinzu.
                </cell>
            </row>
            <row>
               <sortcell sortCrit="remove">
                  <code>private void remove(<a href="#threadGroup">ThreadGroup</a> g)</code>
               </sortcell>
               <cell>Entfernt die Threadgruppe <em>g</em> aus der aktuellen Threadgruppe.</cell>
            </row>
            <row>
               <sortcell sortCrit="add">
                  <code>void add(<a href="#classThread">Thread</a> t)</code>
               </sortcell>
               <cell>Fügt den Thread <em>t</em> zur aktuellen Threadgruppe hinzu.</cell>
            </row>
            <row>
               <sortcell sortCrit="list">
                  <code>public void list()</code>
               </sortcell>
               <cell>Stellt Informationen über die aktuelle Threadgruppe an der Standardausgabe zur Verfügung.<br/>
                Diese Methode ist lediglich zur Fehlersuche sinnvoll einsetzbar.
                <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#list()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="uncaughtException">
                  <code>public void uncaughtException(<a href="#classThread">Thread</a> t, <a fixedType="JDK14" external="yes" offset="java/lang/Throwable.html">Throwable</a> e)</code>
               </sortcell>
               <cell>Wird durch die virtuelle Maschine aufgerufen wenn ein Thread der Gruppe aufgrund einer nicht abgefangenen Ausnahme angehalten wird.<br/>
                Existiert eine Elternthreadgrupe, so wird der Aufruf unverändert an dieselbe Methode dort weitergeleitet.<br/>
                Zusätzlich wird, durch <a fixedType="JDK14" offset="java/lang/Throwable.html#printStackTrace()" keyword="yes" external="yes">printStackTrace</a> der Stackinhalt auf die Standardfehlerausgabe geleitet falls es sich um ein <a fixedType="JDK14" offset="java/lang/ThreadDeath.html" keyword="yes" external="yes">ThreadDeath</a>-Ausnahmeereignis handelt.<br/>
                  <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#uncaughtException(java.lang.Thread, java.lang.Throwable)"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="allowThreadSuspension">
                  <code>public boolean allowThreadSuspension(boolean b)</code>
               </sortcell>
               <cell>Durch die virtuelle Maschine benutzt um im Falle niedrigen verfügbaren Speichers Threads gruppenweise anzuhalten.<br/>
                Diese Methode ist als <em>deprecated</em> gekennzeichnet und sollte nicht mehr verwendet werden!
                <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#allowThreadSuspension(boolean)"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="toString">
                  <code>public String toString()</code>
               </sortcell>
               <cell>Liefert eine Stringrepräsentation der Threadgruppe zurück.<br/>
                Die erzeugte Zeichenkettendarstellung ist der Form:<br/>
                  <b>
                     <em>Klassenname</em>[name=<em>Threadname</em>,maxpri=<em>Prioritätsschranke</em>]</b>,<br/>
                wobei der Klassenname üblicherweise (sofern keine eigene Ableitung von <a href="#threadGroup" keyword="yes">ThreadGroup</a> vorgenommen wurde) <em>java.lang.ThreadGroup</em> lautet.
                <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadGroup.html#toString()"/>
               </cell>
            </row>
         </body>
      </tabular>
      <keyword alt="threadspezifische extern verwaltete Variable">
         <keyword alt="Klasse ThreadLocal">
            <subtopic name="threadLocal">Die Klasse <code>ThreadLocal</code>
            </subtopic>
         </keyword>
      </keyword>
      <p>Die <a fixedType="JDK14" offset="java/lang/ThreadLocal.html" external="yes">Klasse <code>ThreadLocal</code>
         </a> befindet sich im Paket <a fixedType="JDK14" offset="java/lang/package-frame.html" keyword="yes" external="yes">java.lang</a>.<br/>
         <link href="examples/sunSrc/ThreadLocal.java">Quellcode der Klasse <code>ThreadLocal</code>
         </link>
         <br/>
    Die Klasse schafft die Möglichkeit threadspezifische Variablen zu definieren, die außerhalb des Threads verwaltet werden.<br/>
    Implementiert ist die Verwaltung durch eine <a fixedType="JDK14" offset="java/util/HashMap.html" keyword="yes" external="yes">HashMap</a> pro Thread.</p>
      <tabular summary="Operationen der Klasse ThreadLocal in Java 1.4">
         <head length="2">
            <column title="Operation"/>
            <column title="Semantik"/>
         </head>
         <body>
            <row>
               <sortcell sortCrit="a1">
                  <code>ThreadLocal()</code>
               </sortcell>
               <cell>Erzeugt ein <code>ThreadLocal</code>-Objekt.
            <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadLocal.html#ThreadLocal()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="get">
                  <code>public <a fixedType="JDK14" offset="java/lang/Object.html" external="yes">Object</a> get()</code>
               </sortcell>
               <cell>Liefert die threadspezifische Variablenbelegung zurück.<br/>
            Der notwendige Wert innerhalb der <code>HashMap</code> wird beim ersten Aufruf durch den Thread transparent erzeugt.
            <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadLocal.html#get()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="initialValue">
                  <code>protected <a fixedType="JDK14" offset="java/lang/Object.html" external="yes">Object</a> initialValue()</code>
               </sortcell>
               <cell>Liefert den threadspezifischen Vorgabewert der Variable zurück.<br/>
            Ist durch den Programmierer eine andere Initialisierung als <code>null</code> gewünscht, so muß dieses Verhalten durch Ableitung von der Klasse <code>ThreadLocal</code> selbst implementiert werden.
            Hierfür bietet sich die Verwendung anonymer innerer Klassen an.
            <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadLocal.html#initialValue()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="set">
                  <code>public void set(<a fixedType="JDK14" offset="java/lang/Object.html" external="yes">Object</a> value)</code>
               </sortcell>
               <cell>Setzt den threadspezifischen Vorgabewert der Variable auf einen anderen Wert.<br/>
                  <br/>
                  <seeapi ver="1.4" offset="java/lang/ThreadLocal.html#set(java.lang.Object)"/>
               </cell>
            </row>
         </body>
      </tabular>
      <keyword alt="Klasse InheritableThreadLocal">
         <subtopic name="inheritableThreadLocal">Die Klasse <code>InheritableThreadLocal</code>
         </subtopic>
      </keyword>
      <p>Die <a fixedType="JDK14" offset="java/lang/InheritableThreadLocal.html" external="yes">Klasse <code>InheritableThreadLocal</code>
         </a> befindet sich im Paket <a fixedType="JDK14" offset="java/lang/package-frame.html" keyword="yes" external="yes">java.lang</a>.<br/>
         <link href="examples/sunSrc/InheritableThreadLocal.java">Quellcode der Klasse <code>InheritableThreadLocal</code>
         </link>
         <br/>
    Diese Klasse erweitert die zuvor diskutierte Klasse <code>ThreadLocal</code> um die Möglichkeit den aktuellen Zustand der threadspezifischen Variablen an einen Kindthread zu übergeben.</p>
      <tabular summary="Operationen der Klasse InheritableThreadLocal in Java 1.4">
         <head length="2">
            <column title="Operation"/>
            <column title="Semantik"/>
         </head>
         <body>
            <row>
               <sortcell sortCrit="a1">
                  <code>public InheritableThreadLocal()</code>
               </sortcell>
               <cell>Erzeugt ein <code>InheritableThreadLocal</code>-Objekt.<br/>
                  <seeapi ver="1.4" offset="java/lang/InheritableThreadLocal.html#InheritableThreadLocal()"/>
               </cell>
            </row>
            <row>
               <sortcell sortCrit="childValue">
                  <code>protected <a fixedType="JDK14" offset="java/lang/Object.html" external="yes">Object</a> childValue(<a fixedType="JDK14" offset="java/lang/Object.html" external="yes">Object</a> parentValue)</code>
               </sortcell>
               <cell>Berechnet die initialen Belegungen der threadspezifischen Variablen.<br/>
            Dies geschieht durch Abfrage der threadspezifischen Variablen des Elternthreads zum Erzeugungszeitpunkt des Kindthreads.<br/>
            Die Methode wird durch den Elternthread vor Erzeugung des Kindthreads aufgerufen.
            <br/>
                  <seeapi ver="1.4" offset="java/lang/InheritableThreadLocal.html#childValue(java.lang.Object)"/>
               </cell>
            </row>
         </body>
      </tabular>
      <subtopic name="threadStates">Thread-Zustände</subtopic>
      <keyword alt="Thread-Zustände">
         <subtopic>
            <keyword>Zustandsübergänge eines Threads</keyword>
         </subtopic>
      </keyword>
      <illustration id="threadState" gfx="javaThreads/threadStates.gif" width="656" caption="Zustände und Zustandsübergänge eines Java-Threads"/>
      <topic name="sync">Synchronisationskonzepte und -primitive</topic>
      <p>
         <subtopic name="motivation">Zur Motivation ...</subtopic>
      </p>
      <example id="concurrentIncrement" caption="Nebenläufiges Inkrementieren eines Zählers in einer Datei" filename="ConcurrentIncrement.java" output="concurrentIncrement">
         <importText URI="../life/vorlesung/javaThreads/examples/ConcurrentIncrement.java"/>
      </example>
      <p>
         <b>Verhalten:</b> Das Beispiel definiert eine nebenläufige Operation, durch welche ein int-Zählerstand aus einer Datei gelesen wird und um eins erhöht wieder in dieselbe Datei zurückgegschrieben wird.<br/>
    Die Anzahl der nebenläufig auszuführenden Threads kann über einen Komandozeilenparameter festgelegt werden.</p>
      <p>
         <b>Beobachtung:</b> Entgegen der intuitiven Erwartung weißt der Zählerstand in der Datei nach erfolgreichem Ende der Ausführung
    aller erzeugten Threads nicht den vermuteten Wert von 10*Anzahl Threads auf.</p>
      <illustration id="lostUpdatesGfx" gfx="javaThreads/lostUpdates.gif" width="777" caption="Statistische Auswertung der unberücksichtigten Schreibvorgänge"/>
      <p>
         <b>Analyse:</b> Durch Unterbrechung eines Threads nach dem Einlesen des Wertes -- noch vor dem Rückschreiben es inkrementierten
    Zählerstandes -- kann ein anderer Thread zur Ausführung gelangen durch den nochmals der bereits gelesene Zählerstand aus der
    Datei verarbeitet wird.<br/>
    Später wird durch beide Threads derselbe erhöhte Variablenwert rückgeschrieben; ein Erhöhunsvorgang ist daher verloren, da er
    auf veralteten (da bereits (teil-)verarbeiteten) Daten beruht.<br/>
    Die sich zeitlich überscheidenden Threads haben in diese Fall auf inkonsistente Datenstände Zugriff erlangt.<br/>
    Dies muß jedoch in der Ausführung nicht immer der Fall sein. Das Ergebnis der gesamten Programmausführung hängt entscheidend von der Abarbeitungsreihenfolge der Einzelthreads ab.
    Es handelt sich dabei um eine sog. <em>race condition</em>.</p>
      <illustration id="concurrentIncrementGfx" gfx="javaThreads/synchronization.gif" width="400" caption="Lost-Update-Problem durch unsynchronisierte Zugriffe"/>
      <definition id="raceCondition" term="Race Condition">
    Fehlerquelle eines nebenläufigen Programms, die durch unsynchronisierte Abhängigkeiten zwischen Threads entsteht.<br/>
    Abhängig von der tatsächliche Ausführungsreihenfolge der Threads auf dem Prozessor können Fehler in der gesamten Applikationsausführung entstehen.</definition>
      <definition id="atomic" term="Atomar">
    Eine Routine heißt atomar, wenn sie nicht in separate kleinere Einheiten unterteilt werden kann, die während ihrer Ausführung unterbrochen werden können.<br/>
      </definition>
      <definition id="criticalSection" term="kritischer Abschnitt">
    Eine Folge von Anweisungen, deren Ausführung nicht nebenläufig erfolgen kann oder sollte.
    </definition>
      <definition id="resource" term="Ressource">
    Eine Ressource (in der Literatur auch als <keyword>Betriebsmittel</keyword> geführt) bezeichnet eine zur Programmausführung notwendige Einheit.<br/>
Hierbei kann es sich um CPU-Zeit, Variablen- oder Speicherzugriff aber auch um die Verfügbarkeit externer Peripheriegeräte wie Drucker handeln.<br/>
Knappe Ressourcen, um deren Verfübarkeit Konkurrenzsituationen entstehenden werden als <keyword>kritische Ressource</keyword>n bezeichnet.</definition>
      <subsubtopic>Eine erste (naive) Lösung</subsubtopic>
      <p>
         <b>Idee:</b> Konzentration der kritischen Anweisungen in eine einzige Programmzeile.<br/>
    etwa: <code>dos.writeInt( dis.readInt()+1 )</code>.</p>
      <p>
         <b>Kritik:</b> Zwar eine naheliegende Idee, aber keine Problemlösung.<br/>
    Selbst diese vermeintlich atomare Anweisung zerfällt zunächst in eine Fülle von Java-Anweisungen, welche die API-Methoden
    <code>writeInt</code>
         <small>(<a href="examples/sunSrc/writeInt">Quellcode</a>)</small> bzw. <code>readInt</code>
         <small>(<a href="examples/sunSrc/readInt">Quellcode</a>)</small> bilden.<br/>
Darüberhinaus sind selbst diese konstituierenden Java-Anweisungen der API keineswegs atomar, sondern werden ihrerseits die Bytecodeanweisungen der JVM gebildet <small>(Bytecode: <a href="examples/sunSrc/readInt.jasm" keyword="yes">readInt</a>, <a href="examples/sunSrc/writeInt.jasm" keyword="yes">writeInt</a>)</small>.<br/>
Schlußendlich werden die Bytecode-Instruktionen selbst nicht direkt durch die physische Hardware ausgeführt, sondern durch die virtuelle Maschine in native Anweisungen übersetzt.</p>
      <p>Dieser (naive) Ansatz kann daher nicht zur Synchronisation eingesetzt werden!</p>
      <subsubtopic>Eine zweite Lösung</subsubtopic>
      <p>
         <b>Idee:</b> Sicherung des kritischen Bereichs durch Sperroperation.<br/>
    (Vorgriff: Die Implementierung orientiert sich an der Idee der <em>Semaphore</em>.)</p>
      <example id="naiveSynchronization" caption="Naive Sperroperation" filename="UsrLockConcurrentIncrement.java" output="UsrLockConcurrentIncrement" outputMP="UsrLockConcurrentIncrementMP">
         <importText URI="../life/vorlesung/javaThreads/examples/UsrLockConcurrentIncrement.java"/>
      </example>
      <p>
         <b>Analyse:</b> Trotz der guten Absicht bleibt das Problem bestehen.<br/>
    Genaugenommen wurde es lediglich verlagert ...<br/>
    Konnte zuvor der Thread zwischen Lese- und Schreibzugriff auf die Datei unterbrochen werden, so kann dies nun zwischen Anforderung und Erteilung der Sperre geschehen.<br/>
    Überdies verbraucht die gewählte Implementierung ab <a href="#naiveSynchronizationline65">Zeile 65</a> unnötig Rechenzeit durch den aktiven Wartevorgang (<em>
            <keyword>busy waiting</keyword>
         </em>). </p>
      <p>Zur Implementierung ist eine <keyword>unteilbare Hardwareoperation</keyword> notwendig.<br/>
    Kap. 7.2.1.2 des <link href="http://developer.intel.com/design/pentium4/manuals/245471.htm">IA-32 Intel® Architecture Software Developer's Manuals</link> empfiehlt zur Implementierung auf einem IA-32 Prozessor hierfür die Instruktion <code>CMPXCHG</code>.</p>
      <subtopic name="synchronizedKeyword">Das Schlüsselwort <code>synchronized</code>
      </subtopic>
      <p>
         <b>Eigenschaften:</b>
      </p>
      <ul>
         <li>Das Schlüsselwort <code>synchronized</code> gestattet es kritische Abschnitte auf Hochsprachenebene deklarativ zu kennzeichnen.</li>
         <li>Es können sowohl Programmblöcke als auch komplette Methoden als <code>synchronized</code> gekennzeichnet werden.</li>
         <li>Die gesamte Synchronisationlogik wird durch die Java Virtual Machine bereitgestellt.</li>
         <li>Die Durchführung der Synchronisation hat negative Auswirkungen auf die Laufzeit.</li>
      </ul>
      <subsubtopic>
         <keyword>Synchronisation vollständiger Methoden</keyword>
      </subsubtopic>
      <p>
         <b>Idee:</b> Durch Anbringung des Schlüsselwortes in der Signatur einer Methode wird die virtuelle Maschine veranlaßt ein so gekennzeichnete Methode nicht nebenläufig auszuführen. Alle Aufrufe werden strikt serialisiert und ggf. verzögert bis die Methode zum alleinigen Zugriff zur Verfügung steht.</p>
      <p>
         <b>Anwendungsbeispiel:</b> Die Veränderung im Quellcode betrifft ausschließlich <a href="#syncConcurrentIncrementline37">Zeile 37</a>. Dort wird die Methode <code>addOne</code> zusätzlich mit dem Schlüsselwort <code>synchronized</code> versehen.</p>
      <example id="syncConcurrentIncrement" caption="Synchronisation der nebenläufigen Zähler-Inkrementierung durch das Schlüsselwort synchronized" filename="SyncConcurrentIncrement.java" output="SyncConcurrentIncrement" outputMP="SyncConcurrentIncrementMP">
         <importText URI="../life/vorlesung/javaThreads/examples/SyncConcurrentIncrement.java"/>
      </example>
      <p>
         <b>Weiteres Anwendungsbeispiel:</b> Im vorherigen Beispiel war die Synchronisation auf eine Methode angewandt worden, die auf einem (existierenden) Objekt ausgeführt wurde.<br/>
Prinzipiell kann derselbe Mechanismus auch für statische Methoden zur Anwendung gebracht werden.<br/>
Hierbei wird die Sperrinformation nicht durch das Objekt, welches die zu sperrende Methode enthält verwaltet, sondern durch die beherbergende Klasse selbst.</p>
      <p>Zum Beispiel: Der Code simuliert einen Hotelmanager bei der Arbeit. Eine über Kommandozeile übergebene Anzahl gleichzeitig eintreffender Gäste (Threads) möchte das letzte verfügbare Einzelzimmer (statische Methode <code>visit</code>) besuchen.</p>
      <example id="staticLock" caption="Sperrung einer statischen Methode durch das Schlüsselwort synchronized" filename="RoomManager.java" output="RoomManager">
         <importText URI="../life/vorlesung/javaThreads/examples/RoomManager.java"/>
      </example>
      <p>
         <b>
            <keyword>Kritik am synchronized-Ansatz</keyword>:</b>
      </p>
      <p>positiv</p>
      <ol type="decimal">
         <li>Einfache Durchführbarkeit</li>
         <li>Deklarativ</li>
      </ol>
      <p>negativ</p>
      <ol type="decimal">
         <li>Sperrgranularität fixiert auf Methodengröße</li>
         <li>Auswirkungen auf Laufzeit</li>
         <li>Inflexibilität hinsichtlich Anzahl der nebenläufigen Zugriffe (immer auf 1 fixiert)</li>
      </ol>
      <subsubtopic>
         <keyword>Synchronization einzelner Anweisungen</keyword>
      </subsubtopic>
      <p>
         <b>Idee:</b> Behebung des negativen Aspekts (1) unter Beibehaltung der Vorteile (1) und (2).</p>
      <p>
         <b>Lösung:</b> Das bereits bekannte Schlüsselwort <code>synchronized</code> kann innerhalb von Methodenrümpfen zur Bildung synchronisierter Anweisungsblöcke eingesetzt werden.<br/>
Hierbei können nebenläufige Zugriffe auf den Block bezüglich eines beliebigen Objekts serialisiert werden.</p>
      <p>
         <b>Anwendungsbeispiel:</b> In <a href="#syncConcurrentIncrement2line46">Zeile 46</a> wird durch das Schlüsselwort <code>synchronized</code> ein entsprechender Block geöffnet.<br/>
Aufgrund der Restriktion Zugriffe nur hinsichtlich von Objekten serialisieren zu können muß die <a href="#concurrentIncrement">bisherige Implementierung</a> modifiziert werden.<br/>
So muß die als kritische Ressource anzusehende Variable <code>value</code> zwingend als Objekt repräsentiert werden.<br/>
Hierzu wird ab <a href="#syncConcurentIncrement2line89">Zeile 89</a> die Klasse <code>myInteger</code> definiert, die als Prototyp einen <code>int</code>-Wert kapselt. Die Zählerzugriffe werden daher entsprechend umgesetzt.</p>
      <example id="syncConcurrentIncrement2" caption="Synchronisation der nebenläufigen Zähler-Inkrementierung durch einen synchronized-Block" filename="SyncConcurrentIncrement2.java" output="SyncConcurrentIncrement2" outputMP="SyncConcurrentIncrement2MP">
         <importText URI="../life/vorlesung/javaThreads/examples/SyncConcurrentIncrement2.java"/>
      </example>
      <p>
         <b>Äquivalenz der beiden Varianten:</b> Die Wirkung einer <code>synchronized</code>-Methode entspricht einem <code>synchronized</code>-Block, der den gesamten Methodenrumpf umfaßt und bezüglich dem <code>this</code>-Objekt zugriffsserialisiert wird.</p>
      <p>Die Formulierungen:</p>
      <code>
         <pre>public synchronized void foo()
    {
        //...
    } //foo()</pre>
      </code>
      <p>und</p>
      <code>
         <pre>public void foo()
    {
        synchronized(this)
        {
            //...
        } //synchronized
    } //foo()</pre>
      </code>
      <br/>
      <p>sind daher gleichwertig.</p>
      <p>
         <b>
            <keyword>Wirkung der Synchronisationsprimitive <code>synchronized</code>
            </keyword>:</b>
    Die Zugriffsserialisierung mit <code>synchronized</code> erfolgt immer auf Klassen- (für statische Methoden) bzw. auf Objektebene (für Instanzmethoden), trotz der methoden- oder blockspezifischen Schlüsselwortverwendung.<br/>
Insbesondere bei Klassen mit umfangreichem Methodenangebot kann dies signifikant negative Auswirkungen auf die Laufzeit haben.</p>
      <p>
         <b>Anwendungsbeispiel:</b> Das Beispiel definiert zwei statische Methoden (<code>visitRoom</code> in <a href="#doubleSyncedHotelline27">Zeile 27</a> und <code>eat</code> in <a href="#doubleSyncedHotelline43">Zeile 43</a>).<br/>
Beide werden durch nebenläufig ausgeführte Threads unabhängig voneinander aufgerufen.</p>
      <example id="doubleSyncedHotel" caption="Klasse mit zwei synchronisierten Methoden" filename="Hotel.java" output="Hotel">
         <importText URI="../life/vorlesung/javaThreads/examples/Hotel.java"/>
      </example>
      <p>
         <b>Beobachtung:</b> Trotz des unabhängigen nebenläufigen Aufrufs der beide Methoden werden zu keinem Beobachtungszeitpunkt die Rümpfe beider Methoden ausgeführt.</p>
      <p>
         <b>Folgerungen:</b>
      </p>
      <ol>
         <li>Als <code>synchronized</code> deklarierte Methoden werden immer <keyword alt="Synchronisaton, klassenbasierte">klassenbasiert sychronisiert</keyword>, auch wenn sie auf einem Objekt aufgerufen werden.</li>
         <li>Die mit <code>synchronized</code> einhergehenden Sperren werden klassenbasiert (für statische Methoden) und <keyword alt="Synchronisation, objektbasierte ">objektbasiert</keyword> (für Instanzmethoden) verwaltet.<br/>
So können lediglich je eine statische und ein Instanzmethode einer Klasse nebenläufig ausgeführt werden.</li>
      </ol>
      <p>Aussage (2) wird durch das folgende Beispiel illustriert.<br/>
    Nur weil <a href="#mixedSyncedHotelline28">
            <code>visitRoom</code>
         </a> und <a href="#mixedSyncedHotelline44">
            <code>eat</code>
         </a> in unterschiedlichen Kontexten synchronisiert werden ist es möglich diese nebenläufig auszuführen.</p>
      <example id="mixedSyncedHotel" caption="Klasse mit einer statischen und einer Instanzmethode, die beide als synchronized deklariert sind" filename="Hotel2.java" output="Hotel2" outputMP="Hotel2MP">
         <importText URI="../life/vorlesung/javaThreads/examples/Hotel2.java"/>
      </example>
      <p>
         <b>
            <keyword>Explizites Setzen einer klassenbasierten Sperre</keyword>:</b> durch die Angabe des Klassenobjektes (<code>
            <em>Klassenname</em>.class</code>) als Argument des <code>synchronized</code>-Blocks kann expliziter Zugriff auf die klassenbasierte Sperre erlangt werden.<br/>
Das nachfolgende Beispiel zeigt diesen Zugriff in Zeile <a href="#acessingClassLevelLockExplicitlyline49">Zeile 49</a>. Die gewählte Konstellation gestattet die nebenläufige Ausführung der beiden Methoden <code>visitRoom</code> und <code>eat</code>, was an der Ausgabekonstellation <code>thread named Thread-X entered room -- thread named Thread-1 is eating</code> abzulesen ist.</p>
      <example id="acessingClassLevelLockExplicitly" caption="Explizites Setzen einer klassenbasierten Sperre" filename="Hotel4.java" output="Hotel4">
         <importText URI="../life/vorlesung/javaThreads/examples/Hotel4.java"/>
      </example>
      <p>
         <b>Folge in der Praxis:</b> Oftmals wird entweder die Klassensperre zur einfachen Gewinnung einer zweiten Sperre für ein Objekt <gerquot>mißbraucht</gerquot> oder künstliche <code>Serviceobjekte</code> erzeugt, die später als Argumente für <code>synchronized</code>-Blöcke dienen, nur um Zugriff auf ihre Klassensperren zu erlangen.</p>
      <p>
         <b>
            <keyword alt="Beispiele zu synchronized aus der Java-API">Anwndungsbeispiel aus der Java-API</keyword>:</b>
      </p>
      <ol>
         <li>Seit JDK v1.2 steht die Klasse <code>Vector</code>
            <a href="examples/sunSrc/Vector.java">
               <small>(Quellcode ansehen)</small>
            </a>
            <a fixedType="JDK14" offset="java/util/Vector.html">
               <small>(JavaDoc)</small>
            </a> in einer hinsichtlich nebenläufiger Zugriffe abgesicherten Implementierung zur Verfügung.</li>
         <li>Für die Klasse <code>HashMap</code> wird hingegen, wie für alle Klassen des <em>Collection Frameworks</em>, die Zugriffsserialisierung dem Anwender überlassen <a href="examples/sunSrc/HashMap.java">
               <small>(Quellcode ansehen)</small>
            </a>
            <a fixedType="JDK14" offset="java/util/HashMap.html">
               <small>(JavaDoc)</small>
            </a>.</li>
      </ol>
      <p>
         <b>Zusammenfassung:</b> Die verschiedenen Ausprägungen des Schlüsselwortes <code>synchronized</code> können eingesetzt werden um wirkungsvoll die gleichzeitige Abarbeitung von Anweisungsfolgen durch mehr als genau einen Thread zu verhindern.<br/>
Auf diesem Wege läßt sich die konsistente Datenbereitstellung auf dem Wege strikter Serialisierung der Aufrufer eines kritischen Abschnitts realisieren.<br/>
Die Synchronisation ist dabei als <em>wechselseitiger Ausschluß</em> realisiert.</p>
      <definition id="mutex" term="Wechselseitiger Ausschluß">
    Wechselseitiger Ausschluß stellt sicher, daß sich zu jedem Zeitpunkt höchstens eine Programmeinheit (in unserem Falle: Thread) in einem kritischen Abschnitt befindet.<br/>
Hierfür wird der Abschnitt durch einen Sperrmechanismus gesichert, der überwunden werden muß (d.h. die Sperre wird gesetzt) bevor die Ausführung der kritischen Anweisungen gestattet wird. Nach dem Ausführungsende (d.h. Verlassen des kritischen Abschnitts) wird die Sperre wieder freigegeben.<br/>
Während der Ausführungszeit erfolgende weitere Zugriffsversuche werden an der Sperre blockiert und verzögert bis die in Ausführung befindliche Programmeinheit den kritischen Abschnitt erlassen hat.<br/>
Durch den wechselseitigen Ausschluß der nebenläufigen Ausführung von Programmteilen entsteht daher die Illusion einer atomaren Anweisung.</definition>
      <subtopic name="waitNotify">Das Methodenpaar <code>wait</code> und <code>notify</code>
      </subtopic>
      <p>Der Einsatz des Schlüsselwortes <code>synchronized</code> bietet zwar einen leistungsfähigen Mechanismus zur Realisierung des wechselseitigen Ausschlusses an kritischen Abschnitten an. Jedoch treten bei der Realisierung praktischer Probleme zwei entscheidende Einschränkungen zu Tage.</p>
      <ol>
         <li>Der wechselseitige Ausschluß läßt den Eintritt nur genau eines Threads in einen kritischen Bereich zu.</li>
         <li>Die Realisierung der Warteschlangenverwaltung muß durch den Programmierer erfolgen.</li>
         <li>Der Einsatz von <code>synchronized</code> bedingt häufig aktives Warten und damit keinen effizienten Umgang mit Ressource CPU.</li>
      </ol>
      <p>
         <b>Anschauungsbeispiel:</b> Das Hotel der vorangegangenen Beispiele wird auf reale Gegebenheiten adaptiert. Nun sollten zehn gleichzeitig bewohnbare Zimmer sowie ein Speisesaal mit 20 Plätzen zur Verfügung stehen.<br/>
Gäste denen kein Zimmer oder Sitzplatz zur Verfügung steht, warten geduldig bis dies der Fall ist.</p>
      <p>Mit den bishererfügbaren Synchronisationsprimitiven ist dieses Ziel kaum sinnvoll zu erreichen ...</p>
      <ul>
         <li>Einführung einer zusätzlichen Methode zur Anfrage nach knappen Ressourcen.</li>
         <li>Die Implementierung der Anfrage nach den knappen Ressourcen ist strukturell identisch.</li>
         <li>Mehrere <code>synchronized</code>-Routinen behindern sich gegenseitig.</li>
         <li>Die Umsetzung der Warteschlange ist aufwendig.</li>
         <li>Mehrere kritische Abschnitte existieren verteilt im Programm.</li>
      </ul>
      <subtopic name="semaphore">Die Primitive <em>Semaphore</em>
      </subtopic>
      <p>Das bekannte Konzept der Semaphore räumt mit zwei Restriktionen des wechselseitigen Ausschlusses durch <code>synchronized</code> aus:</p>
      <ol>
         <li>Der Limitierung der Sperren auf jeweils eine Klassen- und eine Objektsperre.</li>
         <li>Der Limitierung der gleichzeitigen Zugriffe auf genau einen, sofern dies gewünscht ist.</li>
      </ol>
      <definition id="semaphoreDef" term="Semaphor">
    Das Semaphor (Wortbedeutung: Singalmast, optischer Telegraph) ist ein Variablentyp zur sicheren Zählung von Wartesignalen.<br/>
Ein Semaphor verfügt über die beiden atomaren Operationen <em>p</em> (nach dem holländischen <em>passeeren</em>) und <em>v</em> (<em>vrijgeven</em>) zur Belegung einer durch durch das Semaphor verwalteten Ressource bzw. deren Freigabe.<br/>
Zur korrekten funktionsfähigen Implementierung eines Semaphor ist Unterstützung durch eine unteilbare Hardwareoperation notwendig.
    </definition>
      <p>Implementierung durch eine eigenständige Java-Klasse:</p>
      <example id="semaphore" caption="Eine Semaphore" filename="Semaphore.java">
         <importText URI="../life/vorlesung/javaThreads/examples/Semaphore.java"/>
      </example>
      <p>Eine einfache Erweiterung des klassischen Semaphormechanismus stellt der Übergang von der skalaren Sperrvariablen <code>s</code> zu einem strukturierten Sperrobjekt dar:</p>
      <example id="SemaphoreGroup" caption="Eine Semaphorenumsetzung, die ein Feld von Sperrvariablen kontrolliert" filename="SemaphoreGroup.java">
         <importText URI="../life/vorlesung/javaThreads/examples/SemaphoreGroup.java"/>
      </example>
      <p>Das Beispiel verwaltet den wechselseitigen Ausschluß beim Zugriff auf ein <code>int</code>-Feld. Die Methode <code>changeValues</code> vereinigt die Eigenschaften der klassischen <code>p</code>-Operation und <code>v</code>-Operation in sich.<br/>
Hierdurch wird jedoch die korrekte Behandlung der Sperrvariablenstände zurück zum Anwendungsprogrammierer verlagert!</p>
      <p>
         <b>Anwendungsbeispiel:</b>
      </p>
      <example id="HotelSemaphore" caption="Synchronisation unter Einsatz einer Semaphore" filename="Hotel5.java" output="Hotel5" outputMP="Hotel5MP">
         <importText URI="../life/vorlesung/javaThreads/examples/Hotel5.java"/>
      </example>
      <p>Im Beispiel werden zur Synchronisation die bekannten Primitive verwendet. Zur Realisierung der Warteschlangen werden zwei neue Methoden eingesetzt <code>wait()</code> und <code>notify</code>.</p>
      <p>Die Methode <a fixedType="JDK14" offset="java/lang/Object.html#wait()" keyword="yes">wait()</a> veranlaßt einen Thread auf ein Signal einer anderen Ausführungseinheit zu warten.<br/>
    Signalisiert ein Thread durch <a fixedType="JDK14" offset="java/lang/Object.html#notify()" keyword="yes">notify()</a> das Eintreten eines gewissen Zustandes, so wird der durch Aufruf von <code>wait</code> blockierte Thread geweckt und fährt in seiner Berechnung fort.<br/>
         <code>notify</code> stellt somit eine einfache Möglichkeit der Inter-Threadkommunikation dar.</p>
      <p>
         <code>wait</code> und <code>notify</code> sind selbst kritische Operationen und müssen daher in <code>synchronized</code>-Abschnitte oder -Methoden eingebettet werde.</p>
      <tabular summary="Wait- und Notify-Operationen der Klasse Object in Java 1.4">
         <head length="2">
            <column title="Operation"/>
            <column title="Semantik"/>
         </head>
         <body>
            <row>
               <sortcell sortCrit="wait">
                  <code>public <a fixedType="JDK14" offset="java/lang/Object.html#wait()">wait()</a>
                  </code>
               </sortcell>
               <cell>Wartet auf den Aufruf von <code>notify</code> durch einen anderen Thread.</cell>
            </row>
            <row>
               <sortcell sortCrit="wait">
                  <code>public <a fixedType="JDK14" offset="java/lang/Object.html#wait(long)">wait(long l)</a>
                  </code>
               </sortcell>
               <cell>Wartet höchstes die durch <code>l</code> vorgegebene Zeitspanne in Millisekunden auf den Aufruf von <code>notify</code> durch einen anderen Thread.</cell>
            </row>
            <row>
               <sortcell sortCrit="wait">
                  <code>public <a fixedType="JDK14" offset="java/lang/Object.html#wait(long,int)">wait(long l, int n )</a>
                  </code>
               </sortcell>
               <cell>Wartet höchstens die durch <code>l</code> vorgegebene Zeitspanne in Millisekunden zuzüglich des durch <code>n</code> spezifizierten Zeitraumes in Nanosekunden auf den Aufruf von <code>notify</code> durch einen anderen Thread.</cell>
            </row>
            <row>
               <sortcell sortCrit="notify">
                  <code>public <a fixedType="JDK14" offset="java/lang/Object.html#notify()">notify()</a>
                  </code>
               </sortcell>
               <cell>Weckt genau einen durch <code>wait(...)</code> blockierten Thread.</cell>
            </row>
            <row>
               <sortcell sortCrit="notifyAll">
                  <code>public <a name="notifyAllAPICAll" fixedType="JDK14" offset="java/lang/Object.html#notifyAll()">notifyAll()</a>
                  </code>
               </sortcell>
               <cell>Weckt alle durch <code>wait(...)</code>blockierten Threads.</cell>
            </row>
         </body>
      </tabular>
      <p>Es ist leicht einzusehen, daß der Zugriff auf die Sperrvariable <code>s</code> in den Zeilen <a href="#semaphoreline13">13</a>, <a href="#semaphoreline25">25</a> und <a href="#semaphoreline25">25</a> selbst einen kritischen Abschnitt darstellt und daher synchronisiert werden muß.<br/>
Der Rückgriff auf das bekannte Schlüsselwort <code>synchronized</code> löst das sich ergebende Synchronisationsproblem jedoch strenggenommen nicht, sondern verlagert es in die Hochsprachenebene und delegiert somit die korrekte Durchführung der Synchronisation an Übersetzer und Laufzeitsystem.</p>
      <p>
         <b>Probleme beim Einsatz von <code>wait</code> und <code>notify</code>: </b> Der Aufruf des Methodenpaars <code>wait</code>-<code>notify</code> ist selbst laufzeitkritisch hinsichtlich der Reihenfolge der Aufrufe. In nebenläufigen Ausführungsumgebungen können Bedingungen eintreten, in denen ein Thread sein <code>notify</code>
         <em> vor </em> dem (eigentlich) zugehörigen <code>wait</code> des zu verzögernden Threads aufruft.</p>
      <example id="MissedNotify" caption="Probleme beim Einsatz von Wait und Notify" filename="MissedNotify.java">
         <importText URI="../life/vorlesung/javaThreads/examples/MissedNotify.java"/>
      </example>
      <p>Der Aufruf <code>java MissedNotify  0 50</code> liefert:</p>
      <code>
         <pre>sleeping 'til notification ...
Trying to awake ...
notified and awaked</pre>
      </code>
      <p>
         <code>java MissedNotify  100 50</code> hingegen sorgt dafür, daß <code>notify</code>
         <em> vor </em>
         <code>wait</code> erreicht wird:</p>
      <code>
         <pre>Trying to awake ...
sleeping 'til notification ...
An InterruptedException caught
null
java.lang.InterruptedException
        at java.lang.Object.wait(Native Method)
        at java.lang.Object.wait(Object.java:426)
        at Sleeper.goToSleep(MissedNotify.java:64)
        at Sleeper.run(MissedNotify.java:41)
        at java.lang.Thread.run(Thread.java:536)</pre>
      </code>
      <p>
         <b>Als Lösung </b> bietet es sich an, den Aufruf von <code>wait</code> in eine <code>while</code>-Schleife zu kleiden, die prüft, ob die Bedingung für den Eintritt in den Wartezustand vorliegt.<br/>
Im Beispiel ist dies durch die Variable <code>sleeping</code> in <code>LockObj</code> umgesetzt.<br/>
Der bedingte Aufruf von <code>while</code> findet sich ab <a href="#MissedNotify2line64">Zeile 64</a>.</p>
      <example id="MissedNotify2" caption="Lösung des Problems beim Einsatz von Wait und Notify" filename="MissedNotify2.java">
         <importText URI="../life/vorlesung/javaThreads/examples/MissedNotify2.java"/>
      </example>
      <subtopic name="Monitore">Monitore</subtopic>
      <p>Innerhalb der Java-Laufzeitumgebung werden <em>
            <keyword>Monitor</keyword>e</em> als Hochsprachensynchronisationsprimitive eingesetzt. (siehe <a href="../../files/monitors.pdf">C. A. R. Hoare: <em>Monitors: An Operating System Structuring Concept</em>, Communications of the ACM, Vol. 17, No. 10, Oct. 1974, pp. 549--557</a>).<br/>
Diese werden durch die beiden Bytecodeinstruktionen <a href="../java/kap3.html#monitoroperationen" keyword="yes">monitorenter</a> und <a href="../java/kap3.html#monitoroperationen" keyword="yes">monitorexit</a> direkt von der virtuellen Maschine unterstützt.</p>
      <p>Abbildung <illustrationRef id="Monitor"/> skizziert das Verhalten der virtuellen Maschine bei einer monitorbasierten Synchronisation mittels <code>wait</code> und <code>notify</code>.</p>
      <illustration id="Monitor" gfx="javaThreads/monitor.gif" width="466" caption="Verhalten eines Monitors zur Synchronisation"/>
      <p>Aus dieser Mimik erklärt sich auch die Verwendung von <code>while</code> statt <code>if</code> in <a href="#semaphoreline13">Zeile 13</a> der Semaphorenimplementierung, da andernfalls die Bedingung beim Wiederbetreten des Monitors nach <code>wait()</code> nicht erfüllt sein könnte.<br/>
Zusätzlich läßt die Abbildung deutlich werden, weshalb es während des Wartens innerhalb von <code>wait()</code> (das sich seinerseits in einem <code>synchronized</code>-Block befindet, nicht zu Verklemmungen kommt: <code>wait</code> gibt intern währen des Wartevorganges die gehaltene Sperre frei, so daß ein anderer Programmfaden in einen synchronisierten Abschnitt eintreten und <code>notify</code> aufrufen kann.</p>
      <p>
         <b>Anmerkung:</b>
      </p>
      <ul>
         <li>
            <code>notifyAll</code> deblockiert zwar alle wartenden Threads, da sich deren <code>wait</code>-Aufrufe jedoch in <code>synchronized</code>-Methoden oder -Abschnitten befinden serialisieren sich diese in der Abarbeitung hinsichtlich des Erhalts der Objektsperre.</li>
         <li>Die Java-Spezifikation trifft keinerlei Aussagen darüber in welcher Reihenfolge die blockierten Threads geweckt werden.</li>
         <li>Probleme falls <code>wait</code>- und <code>notify</code>-Aufrufe während der Ausführungsphase nicht korrekt verzahnt abgearbeitet werden.</li>
         <li>Nachteile des Monitoransatzes:
            <ul>
               <li>Monitore bleiben entlang von geschachtelten Aufrufen gesperrt, nur der letzte, <code>wait</code> aufrufende, wird explizit deblockiert.</li>
               <li>Im klassischen Konzept führen externe Einflüsse auf den Monitor (externes Entnehmen aus der Warteschlange) zu Schäden am Monitor.</li>
               <li>Während des Wartens kann ein blockierter Prozeß nicht auf externe Ereignisse reagieren.</li>
               <li>Das Ursprungskonzept sieht kein zeitlich begrenztes Warten vor.</li>
            </ul>
         </li>
      </ul>
      <p>Beispiel <exRef ref="javaMonitor"/> zeigt die Implementierung eines Monitors mit Hilfe der <a href="#semaphore">vorgestellten Semaphoreumsetzung</a>.<br/>
Der Monitor muß vor der Ausführung eines kritischen Abschnitts durch den Programmierer (Aufruf der Methode <a href="#javaMonitorline8" keyword="yes">enter</a>) betreten werden. Entsprechend wird ein Monitor explizit durch <a href="#javaMonitorline12" keyword="yes">leave</a>, sofern keine Threads auf den Eintritt warten, oder <a href="#javaMonitorline16" keyword="yes">notify</a>, falls Threads durch Aufruf von <a href="#javaMonitorline20" keyword="yes">wait</a> auf den Eintritt in den kritischen Abschnitt wartend blockiert wurden, verlassen werden.</p>
      <p>
         <b>Anmerkung:</b>
      </p>
      <ul>
         <li>Keine Methode innerhalb des Monitors ist als synchronized deklariert!<br/>
    Die Synchronisation durch wechselseitigen Ausschluß erfolgt konzentriert in den Objekten der Klasse <a href="#semaphore" keyword="yes">Semaphore.</a>
         </li>
         <li>Die Methoden <a href="#javaMonitorline20" keyword="yes">wait</a> und <a href="#javaMonitorline16" keyword="yes">notify</a> greifen auf eine durch den Aufrufer zu erzeugende Semaphore zurück.<br/>
Sie dient der Steuerung der gleichzeitig im Rumpf eines Monitors zugelassenen aktiven Einheiten.</li>
      </ul>
      <example id="javaMonitor" caption="Implementierung eines Monitors mit Hilfe von Semaphoren" filename="Monitor.java">
         <importText URI="../life/vorlesung/javaThreads/examples/Monitor.java"/>
      </example>
      <topic name="syncProb">Synchronisationsprobleme und ihre Lösung</topic>
      <subtopic name="producerConsumer">
         <keyword>Erzeuger-Verbraucher Problem</keyword>e</subtopic>
      <p>
         <b>Auch bekannt als: </b>
         <em>
            <keyword>Leser-Schreiber-Problem</keyword>
         </em>
      </p>
      <p>
         <b>Motivation: </b> Typische Beziehung: Genau ein oder eine Menge von Produzenten stellen eine Ware oder Dienstleistung zur Verfügung die von genau einem oder einer Menge von Konsumenten entgegengenommen wird.</p>
      <p>Die ausschließliche Verwendung von Semaphoren führt direkten Synchronisation von Erzeuger und Verbraucher, da der Erzeuger nicht <gerquot>auf Vorrat</gerquot> produzieren kann, sondern den Verbraucher immer direkt beliefern muß.</p>
      <p>Das Beispiel simuliert eine Backerei. Der Bäcker (=Produzent) ist in der Lage eine gewisse Anzahl von Kunden (übergebener Komandozeilenparameter als Initialisierung der Semaphore) gleichzeitig zu bedienen. Alle weiteren eintreffenden Kunden müssen waren, bis der Bäcker wieder verfügbar ist.<br/>
Neue Kunden können durch Tastendruck dynamisch erzeugt werden.</p>
      <p>
         <b>Anmerkung: </b> Die Subtraktion vom Schätzwert der aktuell in Ausführung befindlichen Threads in <a href="#BakeryShopline79">Zeile 79</a> liefert ausschließlich für die SUN Java-Referenzimplementierung korrekte Werte, die Anzahl der durch die virtuelle Maschine definierten Threads für Systemaufgaben kann auf anderen Plattformen abweichen.</p>
      <example id="BakeryShop" caption="Erzeuger-Verbraucherproblem am Beispiel einer Bäckerei" filename="BakerySimulation.java" output="bakerySimulation" outputMP="bakerySimulationMP">
         <importText URI="../life/vorlesung/javaThreads/examples/BakerySimulation.java"/>
      </example>
      <p>
         <b>Beobachtung: </b> Bei zunehmender Kundenzahl steigen die Wartezeiten ab einer gewissen Grenze stark an. Trotz der <gerquot>Entschärfung</gerquot> durch die Anzahl der parallel bedienbaren Kunden offenbart sich daher die direkte Kopplung zwischen Erzeuger und Verbraucher als potentieller Engpaß.<br/>
Gleichzeitig fällt auf, daß die freie Kapazität des Bäckers zwischen Kundenbesuchen nicht genutzt wird.</p>
      <p>
         <b>Abhilfe: </b> Einführung eines <keyword>Puffers</keyword> (im Sinne des Beispiels: Regallagers) zur Entkopplung von Produzent und Konsument.</p>
      <example id="Buffer" caption="Datenpuffer zur Entkopplung von Sender und Empfänger" filename="Buffer.java">
         <importText URI="../life/vorlesung/javaThreads/examples/Buffer.java"/>
      </example>
      <p>
         <b>Anmerkungen zum Code: </b>
      </p>
      <ul>
         <li>Die Verwaltung strukturierter Nachrichten, bis hin zu Objektgraphen ist durch die ausschließliche Verwaltung von Daten des Typs <code>Object</code> innerhalb der Standard-API-Klasse <a fixedType="JDK14" offset="java/util/LinkedList.html" keyword="yes">LinkedList</a> (siehe <a href="#Bufferline6">Zeile 6</a>) realisiert.</li>
         <li>Seit Java v1.4 stehen komfortable Methoden zur Umsetzung typspezifischer Puffer für alle <a href="../java/kap2.html#2.2.2">numerischen Primitivtypen</a> (z.B. <a fixedType="JDK14" offset="java/nio/IntBuffer.html" keyword="yes">IntBuffer</a>) zur Verfügung.</li>
      </ul>
      <example id="bakerySimulation2" caption="Erzeuger-Verbraucherproblem am Beispiel einer Bäckerei unter Verwendung eines Puffers" filename="BakerySimulation2.java" output="bakerySimulation2" outputMP="bakerySimulation2MP">
         <importText URI="../life/vorlesung/javaThreads/examples/BakerySimulation2.java"/>
      </example>
      <p>
         <b>Anmerkungen zum Code: </b>
      </p>
      <ul>
         <li>Die Klasse <code>Baker</code> ist ebenfalls nebenläufig realisiert, um die nebenläufige Befüllung des Lagers zu gestatten.</li>
         <li>Der Thread welcher die nebenläufige Klasse <code>Baker</code> kapselt ist als <em>Daemon</em>-Thread definiert, um die Endlosschleife beim Programmende verlassen zu können.</li>
      </ul>
      <p>Neben der Synchronisation der Einzelthreads <em>durch</em> gemeinsame Resourcennutzung kann aber auch die Synchronisation <em>zur</em> gemeinsamen Resourcennutzung in den Vordergrund treten.<br/>
Das bekannteste Beispiel hier dürften gemeinsam genutzte Ressourcen sein, die sowohl von mehreren Lesern als auch Schreibern nebenläufig zugegriffen werden.</p>
      <illustration id="concurrentRWGfx" gfx="javaThreads/concurrentRW.gif" width="628" caption="Nebenläufige Lese- und Schreibvorgänge"/>
      <example id="concurrentRW" caption="Implementierung der Synchronisation nebenläufiger Lese- und Schreibvorgänge mit wait und notify" filename="ReaderWriter.java" output="ReaderWriter" outputMP="ReaderWriterMP" javaDoc="ReaderWriter/index.html">
         <importText URI="../life/vorlesung/javaThreads/examples/ReaderWriter.java"/>
      </example>
      <p>
         <b>Anmerkungen:</b>
      </p>
      <ul>
         <li>Die Implementierung nimmt keine Rücksicht auf doppelt konsumierte Daten. Durch Kombination mit einem Puffer kann dies leicht durch Schreiben aller Produzenten in den Buffer und Entnahme der dort verwalteten Daten durch die Konsumenten realisiert werden.</li>
         <li>Die Lösung bevorzugt beim Lesen die schreibenden Threads (<a href="#concurrentRWline111">siehe Zeile</a>)</li>
         <li>... beim Schreiben wird hingegen nur auf aktive (lese- und schreib-)Threads Rücksicht genommen, wartende Lesethreads bleiben unberücksichtigt (<a href="#concurrentRWline137">siehe Zeile</a>)</li>
      </ul>
      <example id="concurrentRW2" caption="Implementierung der Synchronisation nebenläufiger Lese- und Schreibvorgänge mit Semaphoren" filename="ReaderWriter2.java" output="ReaderWriter2" outputMP="ReaderWriter2MP" javaDoc="ReaderWriter2/index.html">
         <importText URI="../life/vorlesung/javaThreads/examples/ReaderWriter2s.java"/>
      </example>
      <p>
         <b>Anmerkungen:</b>
      </p>
      <ul>
         <li>Das Beispiel verwendet eine gegenüber der ursprünglichen Semaphoren-Implementierung <a href="examples/Semaphore2.java">erweitere Umsetzung</a>, die es gestattet die Sperrvariable vollständig zu belegen, d.h. exklusiven Zugriff zu erlangen.</li>
         <li>Durch die Initialisierung des Semaphor kann, über das bisherige Steuerungsinstrument der Threadanzahl hinaus, die Menge der nebenläufigen Lesevorgänge gesteuert werden.</li>
      </ul>
      <subtopic name="philosophers">Hungrige Philosophen</subtopic>
      <p>Das sog. <em>Problem der hungrigen Philosophen</em> dürfte das bekannteste Synchronisationsproblem überhaupt sein ...</p>
      <p>Die (bekannten) Grundvoraussetzungen:</p>
      <ul>
         <li>
            <em>n </em> hungrige Philosophen um einen runden Tisch</li>
         <li>
            <em>n </em> bereitliegende Gabeln (je nach Phantasie auch Ess-Stäbchen oder ähnliches)</li>
         <li>Zur Nahrungsaufnahme benötigt jeder Philosoph zwei Gabeln</li>
         <li>Nach der Nahrungsaufnahme werden beide Gabeln wieder zurück auf den Tisch gelegt</li>
      </ul>
      <illustration id="philosophers" gfx="javaThreads/philosophen.gif" width="200" caption="Das Philosophen-Problem"/>
      <example id="hungryPhilosophersWaitNotify" caption="Implementierung der hungrigen Philosophen mit wait und notify" filename="HungryPhilosophers.java" outputMP="HungryPhilosophers5MP" output="HungryPhilosophers5">
         <importText URI="../life/vorlesung/javaThreads/examples/HungryPhilosophers.java"/>
      </example>
      <example id="hungryPhilosophersSemaphore" caption="Implementierung der hungrigen Philosophen mit einer Semaphoregruppe" filename="HungryPhilosophers2.java" outputMP="HungryPhilosophers25MP" output="HungryPhilosophers25">
         <importText URI="../life/vorlesung/javaThreads/examples/HungryPhilosophers2.java"/>
      </example>
      <p>Als abschließendes Beispiel <exRef ref="hungryPhilosophersMonitor"/> ist die Umsetzung des <keyword>Philosophenproblem</keyword>s mit Hilfe von Monitoren realisiert.<br/>
Auffallend hierbei ist insbesondere, daß die Methoden <a href="#hungryPhilosophersMonitorline" keyword="yes">useFork</a> und <a href="#hungryPhilosophersMonitor" keyword="yes">releaseFork</a> nicht mehr als <a href="#synchronizedKeyword" keyword="yes">synchronized</a> deklariert werden müssen, da die Realisierung des <a href="#mutes">wechselseitigen Ausschlusses</a> durch den Monitor -- und hierbei durch das dieser Umsetzung zugrundeliegende Semaphor -- erfolgt.<br/>
Ferner ist die Äquivalenz der <a href="#waitNotify">Java-API-Methode <code>wait</code>
         </a> und der <a href="#javaMonitorline20">gleichnamigen Implementierung des Monitors</a> für diesen Anwendungsfall offensichtlich. Vielmehr noch, läßt sich sogar unter Kenntnis der <a href="#semaphore">Implementierung des Semaphor</a> zeigen, daß diese auf die Nutzung des genannten API-Aufrufes zurückzuführen ist.<br/>
Ähnliches gilt im analogen Falle, der Substitution des Aufrufes von <a href="#notifyAllAPICAll" keyword="yes">notifyAll</a> durch die Methode <a href="#javaMonitorline16" keyword="yes">notify</a> (<a href="#hungryPhilosophersMonitorline40">Zeile 40</a>).
</p>
      <example id="hungryPhilosophersMonitor" caption="Implementierung der hungrigen Philosophen mit Hilfe eines Monitors" filename="HungryPhilosophers3.java" outputMP="HungryPhilosophers35MP" output="HungryPhilosophers35">
         <importText URI="../life/vorlesung/javaThreads/examples/HungryPhilosophers3.java"/>
      </example>
      <topic name="deadlock">Verklemmungen</topic>
      <p>Verklemmungen (engl. <em>Deadlocks</em>) sind eine kennzeichnende Fehlersituation die als Folge fehlerhafter oder unzureichender Synchronisation in verteilten und nebenläufigen Abläufen auftreten können.</p>
      <definition id="deadlock" term="Verklemmung">
Eine Menge von Threads befindet sich in einem <keyword>Deadlock</keyword>-Zustand, falls jeder Thread der Menge auf ein Ereignis wartet, daß nur ein anderer Thread der Menge auslösen kann.</definition>
      <p>Ein solches Ereignis kann die Freigabe einer Sperre oder die Verfügbarkeit einer Ressource sein.</p>
      <p>
         <b>Bedingungen für das Auftreten einer Verklemmung:</b>
      </p>
      <ul>
         <li>Seriell nutzbare Ressourcen.<br/>
    Der Zugriff wird zumeist durch wechselseitigen Ausschluß realisiert.</li>
         <li>Inkrementelle Ressourcenaquise.<br/>
    Threads beanspruchen bereits Ressourcen während sie jederzeit weitere nachfordern können.</li>
         <li>Kein Ressourcenentzug.<br/>
    Zugeteilte Ressourcen können nicht extern entzogen werden.</li>
         <li>Zyklische Wartebedingungen.</li>
      </ul>
      <p>
         <b>Bemerkung: </b> Aus Sicht des Programmflusses betrachtet stellt ein Deadlock einen Zustand in einem endlichen Automaten dar, zu ausschließlich eingehende Transitionen existieren.</p>
      <p>Beispiel <exRef ref="simpleDeadlock"/> zeigt eine Implementierung die zu Verklemmungen führen kann, aber nicht muß.<br/>
Das Eintreten einer Verklemmungssituation hängt von der tatsächlichen Reservierungsreihenfolge der ab, die über eine Zufallsvariable in <a href="#simpleDeadlockline35">Zeile 35</a> gesteuert wird.</p>
      <example id="simpleDeadlock" caption="Implementierung einer Konkurrenzsituation um eine Ressource die zu Verklemmungen führen kann" filename="SimpleDeadlock.java">
         <importText URI="../life/vorlesung/javaThreads/examples/SimpleDeadlock.java"/>
      </example>
      <p>
         <b>Ausgabe eines verklemmungssfreien Ablaufs</b>
      </p>
      <code>
         <pre>Thread-2 is sleeping
Thread-1 is sleeping
Thread-1 requests resource #0
Thread-2 requests resource #0
Thread-1 locks resource #0
Thread-1 requests resource #1
Thread-1 locks resource #1
Thread-1 released resource #1
Thread-1 released resource #0
Thread-2 locks resource #0
Thread-2 requests resource #1
Thread-2 locks resource #1
Thread-2 released resource #1
Thread-2 released resource #0
[Programmende]</pre>
      </code>
      <p>
         <b>
            <a name="deadlockResult">Ausgabe Ablaufs der zu einer Verklemmung führt</a>
         </b>
      </p>
      <code>
         <pre>Thread-1 is sleeping
Thread-2 is sleeping
Thread-2 requests resource #0
Thread-1 requests resource #1
Thread-2 locks resource #0
Thread-1 locks resource #1
Thread-2 requests resource #1
Thread-1 requests resource #0
[Programmstillstand, keine weiteren Ausgaben]</pre>
      </code>
      <subtopic>Visualisierung von Verklemmungsszenarien</subtopic>
      <p>Zur Analyse und graphischen Veranschaulichung von Verklemmungsszenarien hat sich die Darstellung als gerichteter Graph eingebürgert.<br/>
Im folgenden ist hierfür folgende symbolische Notation gewählt:</p>
      <ul>
         <li>Threads werden durch beschriftete Knoten repräsentiert.</li>
         <li>Ressourcen werden durch beschriftete Rechtecke repräsentiert.</li>
         <li>Gerichtete Kanten ausgehend von einem Tread <em>t<sub>i</sub>
            </em> zu einer Ressource <em>r<sub>j</sub>
            </em> werden als <em>Thread t<sub>i</sub> fordert Ressource r<sub>j</sub> an</em> interpretiert.</li>
         <li>Gerichtete Kanten ausgehend von einer Ressource <em>r<sub>k</sub>
            </em> zu einem Thread <em>t<sub>l</sub>
            </em> werden als <em>Ressource r<sub>k</sub> ist von Thread t<sub>l</sub> belegt</em> interpretiert.</li>
         <li>Üblicherweise, d.h. sofern nicht anders angegeben kann eine Ressource nur exklusiv belegt werden.</li>
      </ul>
      <p>Treten in einem solchen <keyword>Ressourcengraph</keyword>en zu einem Zeitpunkt Zyklen auf, so liegt ein Verklemmungszustand vor.<br/>
Abbildung <illustrationRef id="deadlockGraph"/> zeigt dies für den <a href="#deadlockResult">oben dargestellten</a> Fall.</p>
      <illustration id="deadlockGraph" gfx="javaThreads/deadlock.gif" width="127" caption="Ressourcengraph einer Verklemmungssituation"/>
      <subtopic name="DLSync">Verklemmt trotzt <code>synchronized</code> ...</subtopic>
      <p>Ähnlich der Verwendung von Semaphoren im vorangegangenen Beispiel, kann der Einsatz von durch die Laufzeitumgebung synchronisierte Abschnitte oder Methoden nicht die Verklemmungsfreiheit eines Ablaufes garantieren. In manchen Fällen kann sie sogar ursächlich für das Eintreten einer Verklemmungssituation sein.</p>
      <p>Beispiel <exRef ref="#synchronizedDL"/> zeigt eine Verklemmung die bei der Verwendung von <code>synchronized</code> geschützten Abschnitten eintritt.<br/>
Der Code simuliert auf einfache Weise Überweisungen die zwischen Konten (modelliert durch Objekte der <a href="#line">Klasse <code>Account</code>
         </a>) vorgenommen werden. Die Ermittlung der beiden beteiligten Konten, sowie des zu transferierenden Betrages erfolgt zufallsgesteuert.<br/>
Vor der Durchführung der Überweisung (<a href="#">Zeile </a>) wird das Quell- und Zielkonto durch wechselseitigen Ausschluß gesperrt. Hierzu werden nacheinander die entsprechenden Objektsperren gesetzt (<a href="#">Zeile </a> und <a href="#"/>).</p>
      <example id="synchronizedDL" caption="Verklemmung bei der Verwendung des Schlüsselwortes synchronized" filename="Bank.java">
         <importText URI="../life/vorlesung/javaThreads/examples/Bank.java"/>
      </example>
      <p>Vereinfachte <b>Ausgabe Ablaufs der zu einer Verklemmung führt</b>
      </p>
      <code>
         <pre>(Thread-2) accounts[4] --40.66333304967762--&gt; accounts[2] started
(Thread-8) accounts[3] --366.4855767109112--&gt; accounts[1] started
(Thread-6) accounts[1] --502.98046127613713--&gt; accounts[4] started
(Thread-10) accounts[4] --184.08552879039075--&gt; accounts[0] started
(Thread-4) accounts[2] --292.5794829489161--&gt; accounts[3] started
(Thread-1) accounts[0] --714.5208007641102--&gt; accounts[4] started
(Thread-7) accounts[0] --170.7740899847421--&gt; accounts[1] started
(Thread-9) accounts[2] --720.4974239388226--&gt; accounts[3] started
(Thread-5) accounts[0] --44.318640244877415--&gt; accounts[2] started
(Thread-3) accounts[1] --390.3961760904666--&gt; accounts[0] started
(Thread-2) account[4] locked
(Thread-8) account[3] locked
(Thread-6) account[1] locked
(Thread-4) account[2] locked
(Thread-1) account[0] locked
[Programmstillstand, keine weiteren Ausgaben]</pre>
      </code>
      <illustration id="syncDL" gfx="javaThreads/syncDL.gif" width="495" caption="Graph der Ressourcenanforderungen"/>
      <p>Der Ressourcengraph aus Abbildung <illustrationRef id="syncDL2"/> ordnet die gewährten Ressourcen den sie belegenden Threads zu (dicke Pfeile) und hebt die an der Verklemmung beteiligten Threads und Ressourcen rot hervor.</p>
      <illustration id="syncDL2" gfx="javaThreads/syncDL2.gif" width="495" caption="Graph der angeforderten und erteilten Ressourcen zum Deadlockzeitpunkt"/>
      <p>
         <b>Analyse: </b> Ursächlich für die Verklemmung ist das unkoordinierte Anfordern der Objektsperren durch <code>synchronized</code>. Die durch jeden Thread implementierte Strategie belegt zunächst (<a href="#synchronizedDLline54">in Zeile 54</a>) das Quellkonto und hält dieses solange belegt bis das Zielkonto (<a href="#synchronizedDL56">in Zeile 56</a>) ebenfalls gesperrt werden kann.<br/>
Eine Verklemmungssituation tritt immer dann auf, wenn sich zur Laufzeit Sperrzyklen wie in Abbildung <illustrationRef id="syncDL2"/> dargestellt ergeben, die Anzahl der beteiligten Threads und Ressourcen kann hierbei durchaus größer zwei sein.<br/>
Im Beispiel wurde gezeigt, daß der Einsatz des Schlüsselwortes <code>synchronized</code> keineswegs a priori alle Synchronisationsprobleme zur Lösung an die virtuelle Maschine delegiert, sondern im Gegenteil -- im Falle des undurchdachten Einsatzes -- selbst zu Verklemmungssituationen führt. Konsequenterweise wirkt sich dies auch auf die höheren Synchronisationsprimitive wie Semaphoren oder Monitore aus, die direkt oder indirekt auf der Anwendung dieses Schlüsselwortes basieren.</p>
      <separator/>
      <p>Abschließend sei gezeigt, daß sich die gezeigte Fehlersituation keineswegs auf den Einsatz von <code>synchronized</code> Realisierung des wechselseitigen Ausschlusses auf Blöcke beschränkt, sondern verhaltensgleich auch für die Anwendung auf Methoden übertragen läßt.</p>
      <p>Der Beispielcode <exRef ref="SyncDL3"/> skizziert eine (naive) objektorietierte Implementierung einer Hüllklasse (engl. <em>wrapper class</em>) (<a href="#SyncDL3line41" keyword="yes">myComplex</a>) für komplexe Zahlen. Diese Klasse bedient sich ihrerseits einer Hüllklasse für ganze Zahlen (<a href="#SyncDL3line78" keyword="yes">myInteger</a>).<br/>
Die komplexen Zahlen <code>1+i2</code> und <code>2+i1</code> werden auf ausgehend von denselben Objekten -- eines für die Zahl <em>1</em> und eines für <em>2</em> -- der Integer-Klasse erzeugt.<br/>
Durch dieses Vorgehen entsteht eine <gerquot>Überkreuzabhängigkeit</gerquot>, dergestalt, daß beide erzeugten komplexen Zahlen speicherintern auf dieselben <code>myInteger</code>-Objekte verweisen.<br/>
Die Fehlersituation, welche dann zur Verklemmung führt, entsteht durch die nebenläufige Operation auf verschiedenen synchronisierten Methoden der Klasse <code>myInteger</code>. Konkret tritt der Stillstand in den Fällen ein, in denen eine Threadumschaltung nach einem Teilzugriff (entweder beim Auslesen des auf Real- oder Imaginärteils) erfolgt. Die Verklemmung tritt dann beim Ausleserversuch des Real- oder Imaginärteils der <gerquot>anderen</gerquot> Zahl auf, die auf dieselben Bestandteile (dieselben Objekte) zurückzuführen ist, auf denen bereits <code>synchronized</code>-Methoden ausgeführt werden.</p>
      <example id="SyncDL3" caption="Verklemmung bei der Verwendung synchronisierter Methoden" filename="SyncDL3.java">
         <importText URI="../life/vorlesung/javaThreads/examples/SyncDL3.java"/>
      </example>
      <illustration id="syncDL3CD" gfx="javaThreads/SyncDL3CD.gif" width="450" caption="Klassendiagramm der statischen Struktur des Beispiels"/>
      <p>Vereinfachte <b>Ausgabe eines Ablaufes der zu einer Verklemmung führt</b>
      </p>
      <code>
         <pre>...
Thread-41 entered add of number c1
Thread-41 entered getRealPart of number c1
Thread-41 entered getRealPart of number c2
Thread-41 calculated real part of number c1
Thread-41 entered getImaginaryPartof number c1
Thread-41 entered getImaginaryPartof number c2
Thread-41 left add of number c1
(Thread-41) 1+i2 + 2+i1 = 3+i3
Thread-144 entered add of number c2
Thread-144 entered getRealPart of number c2
Thread-144 entered getRealPart of number c1
Thread-144 calculated real part of number c2
Thread-144 entered getImaginaryPartof number c2
Thread-144 entered getImaginaryPartof number c1
Thread-144 left add of number c2
(Thread-144) 2+i1 + 1+i2 = 3+i3
Thread-132 entered add of number c2
Thread-132 entered getRealPart of number c2
Thread-129 entered add of number c1
Thread-129 entered getRealPart of number c1
[Programmstillstand, keine weiteren Ausgaben]</pre>
      </code>
      <subtopic name="SemSync">Verklemmt trotz Semaphore ...</subtopic>
      <p>Semaphoren bilden -- bei korrekter Anwendung -- einen gleichermaßen leistungsfähigen wie einfach zu handhabenden Mechanismus zur Synchronisation durch den Applikationsprogrammierer. Werden sie jedoch fehlerhaft eingesetzt, so führt dies unweigerlich zum Auftreten von Verklemmungen.</p>
      <p>Dies läßt sich leicht an einer naheliegenden aber fehlerhaften Umsetzung des Philosophenproblems verdeutlichen:</p>
      <example id="SemDL" caption="Fehlerhafte Implementierung des Philosophenproblems mit Semaphoren" filename="HungryPhilosophers4.java">
         <importText URI="../life/vorlesung/javaThreads/examples/HungryPhilosophers4.java"/>
      </example>
      <p>Das Beispiel realisiert eine naive Ressourcenbelegungsstrategie, da es zunächst einen Teil der benötigten Ressourcen (im Beispiel die linke Gabel) reserviert und dann -- unter Erhalt der Sperre -- auf die Verfügbarkeit der weiteren Ressourcen (im Beispiel die rechte Gabel) wartet.<br/>
Wurde diese Ressource bereits belegt und tritt zusätzlich eine Anforderung an die gesperrte Ressource des bereits wartenden Threads auf, so tritt der Verklemmungsfall ein.</p>
      <p>Eine typische <b>Programmausgabe</b>:</p>
      <code>
         <pre>Philosopher #1 is thinking
Philosopher #3 is thinking
Philosopher #2 is thinking
Philosopher #2 received left fork
Philosopher #1 received left fork
Philosopher #3 received left fork
[Programmstillstand, keine weiteren Ausgaben]</pre>
      </code>
      <p>Bis zum Eintritt der Verklemmung kann unterschiedlich viel Zeit vergehen und zuvor durchaus eine Reihe korrekter Ressourcenverteilungsvorgänge abgewickelt werden. (<a href="output/SemDL">Beispiel</a>)</p>
      <p>Auch Semaphoren stellen sich damit keineswegegs als Verklemmungsvermeidungsmechanismus dar, sondern zeigen, daß die unsachgemäße Handhabung dieser höheren Synchronisationsprimitive durchaus zu Deadlocksituationen führen kann.</p>
      <subtopic name="DLAvoidance">Strategien zur Vermeidung von Verklemmungen</subtopic>
      <p>Durch die aufgezeigten Beispiele wird deutlich, daß sich Verklemmungen nicht a priori durch Hochsprachen oder -Übersetzermechanismen erkennen und vermeiden lassen, sondern das sie zumeist aus der fehlerhaften Verwendung der Synchronisationsmechanismen resultieren.<br/>
Aus diesem Grunde lassen sich auch keine algorithmischen Strategien zur Aufdeckung von potentiell verklemmungsgefährlichen Situationen formulieren, sondern lediglich bewährte Verhaltensweisen formulieren um Verklemmungen vorzubeugen.</p>
      <ul>
         <li>Anforderung von kritischen Ressourcen sollte ausschließlich dann geschehen, wenn zum Anforderungszeitpunkt keine keine anderen Ressourcensperren gehalten werden.</li>
         <li>Zur Vermeidung zyklischer Wartebedingungen sollten Ressourcen immer in derselben Reihenfolge angefordert werden.</li>
         <li>Erfüllung einer Sperranforderung nur, wenn durch sie keine Verklemmung entstehen kann.</li>
         <li>Einführung eines separaten <em>Ressourcenverwalters</em>.</li>
      </ul>
      <subsubtopic>Realisierungen</subsubtopic>
      <p>Das Beispiel <exRef ref="rMgr"/> zeigt die Umsetzung einer Resourcenverwalterklasse.</p>
      <example id="rMgr" caption="Erste Implementierung eines Resourcenverwalters" filename="ResourceMgr.java">
         <importText URI="../life/vorlesung/javaThreads/examples/ResourceMgr.java"/>
      </example>
      <p>Die Implementierung verwendet die Klasse <a href="#SemaphoreGroup" keyword="yes">SemaphoreGroup</a>, die das gleichzeitige setzen mehrerer Semaphor-Sperren gestattet.<br/>
Jedoch garantiert der Einsatz eines Resourcenverwalters, wie dem des Beispiels, keine Verklemmungsfreiheit. Vielmehr bleibt das ursächliche Problem unverändert bestehen, wie die nachfolgende Umsetzung zeigt:</p>
      <example id="DLrMgr" caption="Verklemmung trotz Resourcenmanager" filename="DeadLockWithResourceMgr.java">
         <importText URI="../life/vorlesung/javaThreads/examples/DeadLockWithResourceMgr.java"/>
      </example>
      <p>
         <b>Ausgabe des Programms</b>:</p>
      <code>
         <pre>Thread-1 is sleeping
Thread-2 is sleeping
Thread-1 requests resources [0,1]
Thread-2 requests resources [1,0]
Thread-1 locks resources [0,1]
Thread-2 locks resources [1,0]
Thread-1 requests resources [1,0]
Thread-2 requests resources [0,1]
[Programmstillstand, keine weiteren Ausgaben]</pre>
      </code>
      <p>Als Lösung bietet sich die Implementierung einer Resourcenverteilungsstrategie an.<br/>
Hierbei können je nach Bedarf die eingangs erwähnten Strategien verwirklicht werden.</p>
      <topic name="adv">Weiterführende Konzepte</topic>
      <subtopic name="pri">Prioritäten</subtopic>
      <p>Die Java-Laufzeitumgebung weist jedem Thread bei seiner Erzeugung eine <a href="#priAtt">
            <keyword>Priorität</keyword>
         </a> zu, die während der Laufzeit zur Ermittlung der für zuzuteilenden CPU-Zeit herangezogen werden. Sofern durch den Programmierer nicht anders festgelegt oder beeinflußt <a href="#threadCreationPri">erhält jeder neu erzeugte Thread die Priorität seines Elternthreads</a> dessen Priorität sich wiederum nach der Prozeßpriorität der virtuellen Maschine im Betriebsystem richtet.</p>
      <p>
         <b>Einführendes Beispiel</b> :</p>
      <example id="priorityEx" caption="Threads mit verschiedener Priorität" filename="PriorityExample.java">
         <importText URI="../life/vorlesung/javaThreads/examples/PriorityExample.java"/>
      </example>
      <p>Das Beispiel erzeugt eine durch den Anwender festlegbare Anzahl nebenläufiger Programmfäden, die anwendergesteuert mit verschiedenen Prioritäten versehen werden können. Jeder Thread inkrementiert einen als Klasse realisierten Zähler bis zur selben (über Kommandozeilenparameter festgelegten) Obergrenze.<br/>
Nach Erreichen der Zählgrenze gibt jeder Thread den benötigten Zeitraum und die ihm zugewiesene Priorität aus.</p>
      <p>
         <b>Beobachtungen</b>:</p>
      <code>
         <pre>$java PriorityExample 10000000
Thread with priority 10 took 110ms
Thread with priority 8 took 109ms
Thread with priority 5 took 313ms
Thread with priority 9 took 344ms
Thread with priority 6 took 110ms
Thread with priority 7 took 109ms
Thread with priority 3 took 500ms
Thread with priority 4 took 188ms
Thread with priority 1 took 141ms
Thread with priority 2 took 140ms</pre>
      </code>
      <code>
         <pre>$java PriorityExample 5000000000
Thread with priority 10 took 56219ms
Thread with priority 9 took 86578ms
Thread with priority 8 took 117844ms
Thread with priority 6 took 162438ms
Thread with priority 7 took 177562ms
Thread with priority 5 took 220375ms
Thread with priority 4 took 245391ms
Thread with priority 3 took 274703ms
Thread with priority 1 took 317985ms
Thread with priority 2 took 340781ms</pre>
      </code>
      <ul>
         <li>Die Prioritäten haben (erwartungsgemäß) Einfluß auf die Zuteilung der CPU-Zeit an einen Thread.</li>
         <li>Eine höhere Priorität bedeutet im absoluten Sinne nicht unbedingt eine schnellere Ausführung als eine niedere.<br/>
So benötigt der Thread mit Priorität sechs genausoviel Rechenzeit (110ms) wie der höchstpriore (Priorität 10).<br/>
Bei hinreichend langer Ausführungszeit (zweite Ausgabe) tritt jedoch der erwartete Effekt deutlicher, nicht jedoch in der intuitiv erwarteten Klarheit, zu Tage.</li>
      </ul>
      <p>
         <b>Folgerungen</b>:<br/>
Der Zusammenhang zwischen Prioritätsangaben und CPU-Zuteilung ist nicht unbedingt gegeben. Letztlich hängt die Ressourcenzuteilung an einen Thread von Faktoren wie der eingesetzten virtuellen Maschine, aber auch dem ausführenden Betriebsystem sowie der Lastsituation zum Ausführungszeitpunkt ab.<br/>
Einsatzempfehlungen sind daher für Prioritäten nur schwer zu geben, eine denkbare Möglichkeit wäre die Klassifizierung von Threads in Hintergrundthreads, die ausschließlich mit Rechenaufgaben beschäftigt sind und im Vordergrund mit dem Benutzer interagierende Programmfäden (z.B. GUI-Elemente). Hier böte sich die Bevorzugung der interaktiven Ausführungseinheiten an.<br/>
Keinesfalls sollten Prioritäten zur Umsetzung oder Unterstützung von Wartestrategien oder Synchronisationsbedarfen eingesetzt werden!</p>
      <p>Vorgabebemäß bildet die Java-Laufzeitumgebung jeden Java-Thread in einen Thread des ausführenden Betriebsystems ab, sofern diese Primitive dort zur Verfügung steht.<br/>
Auf einzelnen Plattformen (o.a. Linux und Solaris) kann die Threadverwaltung vollständig in die virtuelle Maschine verlagert werden. Beim Einsatz dieser -- <em>
            <keyword>green threads</keyword>
         </em> benannten Mimik -- werden die Threads durch die virtuelle Maschine simuliert und auf genau einen singlethreaded Prozeß des Betriebssystems abgebildet.</p>
      <p>Im Falle der Transparenz der Threads für das zugrundeliegende Betriebssystem werden auch die javaseitigen Threadprioritäten auf die durch das Betriebssystem angebotenen abgebildet.<br/>
Hierbei nehmen auf die tatsächliche Priorität eines betriebssystemseitigen Threads sowohl die Priorität des Prozesses der virtuellen Maschine als auch die Festlegung der Threadpriorität in Java Einfluß.<br/>
Die nachfolgende Tabelle stellt die möglichen Kominationen für die SUN Referenzimplementierung J2SE v1.4 (build 92) auf der Win32-Plattform zusammen.</p>
      <illustration id="GfxPriorities" gfx="javaThreads/priority.gif" width="500" caption="Abbildung der Java Threadprioritäten auf die der Win32 Betriebssystemplattform"/>
      <separator/>
      <p>Neben der Priorität beeinflußt zusätzlich der <em>Dämon-Status</em> das Ausführungsverhalten eines Threads. Zwar wird sich die Charakterisierung als Dämon-Thread nicht zur Laufzeit auf die CPU-Nutzung eines Threads aus, sie ist aber dafür verantwortlich wann ob das Laufzeitende eines Threads vorzeitig (d.h. vor Ende seiner Aufgabe) extern impliziert werden kann. Damit unterscheidet sich der endgültige Entzug der CPU und das Entfernen der Threadstrukturen aus dem Hauptspeicher von der Terminierung mittels <a href="#interrupt" keyword="yes">interrupt</a>, welches den Thread explizit in seiner Ausführung unterbricht.</p>
      <definition id="daemonDef" term="Dämon-Thread">
Ein Dämon-Thread ist ein Thread der durch die Java-API-Funktion <a href="#setDaemonAPI" keyword="yes">setDaemon</a> vor dessen Ausführungsbeginn als Dämon-Thread ausgezeichnet wurde.<br/>
Zum Zeitpunkt der Terminierung eines Threads prüft die virtuelle Maschine ob sich nach dem Ende des aktuellen Threads ausschließlich lauffähige Dämon-Threads im System befinden. Ist dies der Fall, so wird die applikationsausführung beendet, obwohl sich noch (Dämon-)Threads im <a href="#threadStates">Zustand lauffähig</a> befinden.
</definition>
      <p>In Abgrenzung zu den Dämon-Threads klassifiziert Java die nicht-Dämon-Threads als <em>
            <keyword>Anwender-Thread</keyword>s</em>.<br/>
Grundidee dieser Unterscheidung ist ein Vorgriff auf die Anwendungsmöglichkeiten dieses Konzeptes. So sollen Dämon-Threads, wegen ihrer unvorhersehbaren Eigenschaften nicht zur Resultatberechnung eingesetzt werden, sondern ausschließlich zur Umsetzung unterstützender Dienstleistungen an andere Threads währen deren Laufzeit.<br/>
Aus diesem Grunde setzen einige Implementierung, die den Garbage Collector als eigenständige Thread realisieren diesen als Dämon-Thread um, da seine Dienste nach Ausführungsende der resultatberechnenden Threads nicht mehr benötigt werden.</p>
      <p>Die Applikation <em>
            <a href="#threadInfo">ThreadInfo</a>
         </em> ermittelt Informationen zu allen für den Anwender sichtbaren Threads innerhalb der Laufzeitumgebung. Wird sie mit dem Parameter <code>-gui</code> gestartet, so zeigt sie auch ein AWT-basiertes Fenster um die Erzeugung der Threads für die Verwaltung der interaktiven Abläufe zu initiieren.</p>
      <example id="threadInfo" caption="Ermittlung threadspezifischer Information" filename="ThreadInfo.java">
         <importText URI="../life/vorlesung/javaThreads/examples/ThreadInfo.java"/>
      </example>
      <a name="threadTable">
"<tabular summary="Übersicht der Java-Standardthreads und ihrer Eigenschaften in Java v1.4">
            <head length="4">
               <column title="Name"/>
               <column title="Thread Priorität"/>
               <column title="Threadtyp"/>
               <column title="Bemerkung"/>
            </head>
            <body>
               <row>
                  <cell>Reference Handler</cell>
                  <cell>10</cell>
                  <cell>Dämon</cell>
               </row>
               <row>
                  <cell>Finalizer</cell>
                  <cell>8</cell>
                  <cell>Dämon</cell>
                  <cell>Aufgrund der Organisation als Dämon-Thread ist der Aufruf der Methode <code>finalize</code> vor dem Applikationsende nicht gewährleistet.</cell>
               </row>
               <row>
                  <cell>Signal Dispatcher</cell>
                  <cell>10</cell>
                  <cell>Dämon</cell>
               </row>
               <row>
                  <cell>CompileThread0</cell>
                  <cell>10</cell>
                  <cell>Dämon</cell>
               </row>
               <row>
                  <cell>main</cell>
                  <cell>5</cell>
                  <cell>User</cell>
                  <cell>Die standardmäßig zugewiesene Priorität entspricht <a href="#normPri" keyword="yes">NORM_PRIORITY</a>.</cell>
               </row>
               <row>
                  <cell>AWT-Shutdown</cell>
                  <cell>8</cell>
                  <cell>User</cell>
                  <cell>Thread wird nur bei Verwendung der AWT-/Swing-Bibliothek erzeugt.</cell>
               </row>
               <row>
                  <cell>AWT-Windows</cell>
                  <cell>6</cell>
                  <cell>Dämon</cell>
                  <cell>Thread wird nur bei Verwendung der AWT-/Swing-Bibliothek erzeugt.</cell>
               </row>
               <row>
                  <cell>AWT-EventQueue-0</cell>
                  <cell>6</cell>
                  <cell>Dämon</cell>
                  <cell>Thread wird nur bei Verwendung der AWT-/Swing-Bibliothek für sichtbare Interaktionselemente erzeugt.</cell>
               </row>
            </body>
         </tabular>
      </a>
      <p>Beispiel <exRef ref="daemonDemo"/> startet zwei Threads, die beide jeweils einen threadlokalen Zähler inkrementieren. Der als <em>Daemon</em> benannte Thread ist als Dämon-Thread deklariert, der andere als Anwenderthread.<br/>
Durch Kommandozeilenparamter kann der jeweils zu erreichende Zählerhöchststad pro Thread eingestellt werden.</p>
      <example id="daemonDemo" caption="Verhalten eines Dämon-Threads" filename="DaemonDemo.java" output="DaemonDemo">
         <importText URI="../life/vorlesung/javaThreads/examples/DaemonDemo.java"/>
      </example>
      <p>Eine mögliche <b>Ausgabe</b>:</p>
      <code>
         <pre>$java DaemonDemo 100 10
Daemon's counter state: 1
Daemon's counter state: 2
Daemon's counter state: 3
Daemon's counter state: 4
Daemon's counter state: 5
Daemon's counter state: 6
Daemon's counter state: 7
Daemon's counter state: 8
Normal's counter state: 1
Normal's counter state: 2
Normal's counter state: 3
Normal's counter state: 4
Normal's counter state: 5
Normal's counter state: 6
Normal's counter state: 7
Normal's counter state: 8
Normal's counter state: 9
Normal's counter state: 10
Daemon's counter state: 9
Daemon's counter state: 10
Daemon's counter state: 11
Daemon's counter state: 12
Daemon's counter state: 13
Daemon's counter state: 14
Daemon's counter state: 15
Daemon's counter state: 16
Daemon's counter state: 17</pre>
      </code>
      <p>
         <b>Beobachtung</b>: Beide Zählthreads inkrementieren ihre Zähler nebenläufig, solange bis der Anwenderthread seinen Höchststand erreicht und terminiert. Nachdem der aus der main-Methode resultierende Hauptausführungsthread (ebenfalls ein Anwenderthread) bereits nach Abarbeitung aller seiner Anweisungen (konkret: der Erzeugung der beiden Threads) terminierte existiert zu diesem Zeitpunkt kein Anwender-Thread mehr im System und die Applikation wird bei der nächsten Prozessorzuteilung an den Thread <em>Normal</em> beendet unabhängig davon in welchem Ausführungszustand sich der Dämon-Thread befindet.</p>
      <illustration id="daemonDemoGfx" gfx="javaThreads/daemonDemo.gif" width="250" caption="Ausführungsablauf unter Einsatz eines Dämon-Threads"/>
      <p>Abbildung <illustrationRef id="daemonDemoGfx"/> zeigt verkürzt einen dynamischen Ausführungsablauf des Beispielprogramms.<br/>
Auffallend ist insbesondere, daß die Applikation nicht unverzüglich nach dem Erreichen des Zählerhöchststandes durch den Anwenderthread <em>Normal</em> terminiert, sondern dies erst nach der der Neuzuteilung der CPU erfolgt. Während dieses Zeitraumes wird der Dämon-Thread weiter ausgeführt.</p>
      <subtopic name="scheduling">Scheduling</subtopic>
      <p>Ausgehend von den zugeordneten Prioritäten teilt die Java-Laufzeitumgebung jedem Thread im sog. <em>Schedulingvorgang</em> Rechenzeit zu.<br/>
Die interne Realisierung dieses Zuteilungsschemas ist nicht einheitlich spezifiziert und kann daher zwischen verschiedenen virtuellen Maschinen variieren.</p>
      <p>Üblicherweise wird ein prioritätsgesteuertes <keyword>Round-Robin-Verfahren</keyword> verwirklicht, das zumeist durch einen preemptiven Scheduler ausgeführt wird. Dies läßt sich an den Ausgaben der bisher angegebenen Beispiele ablesen, da in ihnen der Entzug der CPU auch im <a href="#threadState">Zustand <em>laufend</em>
         </a> eintritt.<br/>
Es sind jedoch auch virtuelle Maschinen verfügbar, die <keyword>kooperatives Scheduling</keyword> zugrunde legen. In diesen Umgebungen muß durch den Programmierer sorge für die Abgabe der <keyword>Zeitscheibe</keyword> während rechenintesiver Vorgänge getragen werden. Tritt während des Programmablaufes keine Wartebedingung (etwa auch E/A-Operationen, <code>sleep</code>-Aufrufe oder <code>wait</code>-Aufrufe) ein, so muß zur <keyword>Threadumschaltung</keyword> in regelmäßigen Abständen die API-Methode <a href="#yield" keyword="yes">yield</a> aufgerufen werden.<br/>
Ihr Aufruf in preemptiven Umgebungen wirkt sich ebenfalls auf das Umschaltverhalten aus und läßt im allgemeinenenen flüssigeren Eindruck der Nebenläufigkeit entstehen.</p>
      <example id="yieldEx" caption="Verwendung der Methode yield" filename="DaemonDemo2.java" output="DaemonDemo2">
         <importText URI="../life/vorlesung/javaThreads/examples/DaemonDemo2.java"/>
      </example>
      <p>Beispiel <exRef ref="yieldEx"/> illustriert Verwendung und Auswirkung der <code>yield</code>-Methode. Durch den expliziten Aufruf nach Ausgabe des Zählerstandes wird durch den Thread selbst der Übergang in den <a href="#threadState">Zustand <em>nicht laufend</em>
         </a> herbeigeführt und so in anderer rechenbereiter Thread zur Ausführung gebracht.</p>
      <subtopic name="threadPooling">Thread Pooling</subtopic>
      <p>
         <b>Grundidee</b>
      </p>
      <ul>
         <li>Anwendergesteurte Ressourcenkontrolle und -zuteilung.<br/>
        Aus Gründen der Lastverteilung kann es sinnvoll sein die Anzahl der zu einem Zeitpunkt der zugelassenen nebenläufigen Programmfäden zu begrenzen.</li>
         <li>Erreichung positiver Laufzeitaspekte.<br/>
        Aus der Vorhaltung von Threads kann sich, insbesondere bei einer großen Anzahl kurzlaufender Threads ein Geschwindigkeisvorteil ergeben.</li>
      </ul>
      <p>
         <b>Funktionelle Charakteristika der Lösung</b>:</p>
      <ul>
         <li>Erzeugung einer statischen Anzahl von Threads, die auf Aufgaben warten.</li>
         <li>Verwaltung dieser Threads in einem Ressourcen-Pool.</li>
         <li>Bei Eintreffen einer neuen Aufgabe erfolgt die Entnahme eines vorbereiteten Threads aus diesem Pool und Zuweisung der Aufgabe.</li>
         <li>Ist kein Thread im Pool mehr verfügbar, so wird die anstehende Aufgabe solange verzögert, bis dies wieder der Fall ist.</li>
         <li>Nach Abarbeitung der Aufgabe wird der Thread zurück in den Pool gestellt.</li>
      </ul>
      <p>
         <b>Technische Charakteristika der Lösung</b>:</p>
      <ul>
         <li>Realisierung mit Java-Threads.</li>
         <li>Verwaltung des Thread-Pools mit den Möglichkeiten der Java Collection API.</li>
         <li>Alle Aufgaben realisieren die Schnittstelle <code>Runnable</code>.</li>
         <li>Die Threadverwaltung ist selbst als nebenläufiger Thread realisiert.</li>
      </ul>
      <p>
         <b>Implementierung:</b>
      </p>
      <p>... siehe Vorlesungsergebnisse</p>
      <topic name="application">Anwendungsbeispiele</topic>
      <subtopic name="alg">Algorithmische Aspekte</subtopic>
      <p>Dieses Teilkapitel stellt exemplarisch an der Modifikation des
bekannten Sortierverfahren <em>
            <keyword>Quick Sort</keyword>
         </em>
einige Schritte und Überlegungen dar, die bei der
<keyword>Umsetzung nicht-nebenläufiger Algorithmen in
nebenläufige Analoga</keyword> eine Rolle spielen.</p>
      <p>Um den folgenden Bemühungen eines gleich vorauszuschicken: Der
zu erwartende Geschindigkeitsgewinn hält sich trotz der
hervorragenden Nebenläufigkeitseigenschaften von Quick Sort in
sehr engen Grenzen.<br/> Tests aus der Praxis zeigen, daß er in
vielen Fällen sogar zu vernachlässigen ist, ja mehr noch -- sogar
negative Effekte zeigt --, und daher zumeist unterbleiben
kann.<br/>

Dennoch eignet sich Quick Sort wegen seiner einfachen Struktur
und der bekannten und gut erforschten Eigenschaften als
Studienobjekt.</p>
      <p>
         <b>Ausgangssituation</b>:</p>
      <example id="QSseq" caption="Sequentielle Quick Sort-Implementierung" filename="QuickSort.java">
         <importText URI="../life/vorlesung/javaThreads/examples/QuickSort.java"/>
      </example>
      <p>Beispiel <exRef ref="QSseq"/> zeigt eine sequentielle (d.h.
nicht nebenläufige) rekursive Implementierungsvariante von Quick
Sort.<br/>

Als Pivot-Element, dasjenige bezüglich dem die übrigen Elemente
einer Sortierparition umzugruppieren sind ist statisch auf die
rechnerische Mitte der Partition festgelegt.<br/>

Ferner vermeidet die angegebene Implementierung unnötige
Verauschungsoperationen und Rekursionsschritte.</p>
      <p>
         <b>Einführung von Nebenläufigkeit</b>:</p>
      <p>Im allgemeinen kommt drei Einzelaspekten eine zentrale Rolle
bei der Einführung von Nebenläufigkeit zu:</p>
      <ul>
         <li>Ermöglichung des Zugriff auf gemeinsame Datenbereiche</li>
         <li>Synchronisation</li>
         <li>Organisation der Nebenläufigkeit</li>
      </ul>
      <example id="QSconc" caption="Nebenläufige Quick Sort-Implementierung" filename="cQuickSort.java" outputMP="cQuickSortMP">
         <importText URI="../life/vorlesung/javaThreads/examples/cQuickSort.java"/>
      </example>
      <p>Die threadbasierte nebenläufige Implementierung ersetzt
zunächst die beiden Rekursionschritte der Zeilen <a href="#QSseqline30">30</a> und <a href="#QSseqline32">32</a>
durch Threaderzeugungen. Ferner wird auch der erste Aufruf des
Algorithmus als Ausführung eines Threads umgesetzt.</p>
      <p>Neben dem javaspezifischen Problem der Organisation der
Parameterübergabe durch die Konstruktormethode statt einer
direkten Möglichkeit gewinnt der Aspekt der evtl. zu leistenden
Synchronisation zwischen den Einzelthreads besonderes
Gewicht.<br/>

Hierbei sind zunächst durch Analyse der durch jeden Thread
zugegriffenen Datenbereiche die potentiell gleichzeitig im
konkurrierenden Zugriff befindlichen Ressourcen zu ermitteln.</p>
      <p>Abbildung <illustrationRef id="gfxCQS"/> illustriert die durch
die Einzelthreads verarbeiteten Feldelemente und stellt
zusätzlich die Erzeugungsstruktur der Threads im zeitlichen
Verlauf dar.</p>
      <p>Auffallend hierbei ist, daß konkurrierende Datenzugriffe  --
bedingt durch die Struktur des Quick Sort Algorithmus --
ausschließlich durch Kindthreads eines gegebenen Threads
erfolgen.</p>
      <p>Eine Synchronisation müßte daher lediglich zwischen Threads
und ihren Abkömmlingen durchgeführt werden.</p>
      <p>Durch die Struktur der Algorithmus wird jedoch klar, daß auch
dies nicht zu erfolgen braucht, da die gesamten modifizierenden
Datenzugriffe in Zeile <a href="#QSconcline57">57</a> erfolgen
und demnach <em>vor</em> der Erzeugung der Kindthreads (in Zeile
<a href="#QSconc67">67</a> bzw. <a href="#QSconcline71">71</a>)
abgeschlossen sind.<br/> Eine explizite Synchronisation muß daher
im vorliegenden Falle nicht erfolgen.</p>
      <illustration id="gfxCQS" gfx="javaThreads/cQS.gif" width="350" caption="Erzeugungsgraph der einzelnen Threads"/>
      <subtopic name="gui">Graphische Benutzeroberflächen</subtopic>
      <p>Wie bereits in der <a href="#threadTable">Threadübersichtstabelle</a> gezeigt verwendet das <em>Abstract Windowing Toolkit</em> und die Oberflächenbibliothek <em>Swing</em> bereits intern eigene Threads.<br/>
Nachfolgend werden die Möglichkeiten des Thread-Einsatzes im Umfeld graphischer Benutzeroberflächen eingeführt.</p>
      <example id="swing1" caption="Einfach Swing-Applikation" filename="HelloSwing.java">
         <importText URI="../life/vorlesung/javaThreads/examples/HelloSwing.java"/>
      </example>
      <p>Das Beispiel <exRef ref="swing1"/> verwendet im angegebenen Code keine (anwenderdefinierten) Threads.<br/>
Dennoch deutet das Verhalten der Applikation, insbesondere die fortgesetzte Ausführung obwohl die <code>main</code>-Methode abgearbeitet wurde, auf die Existenz von (nicht-Daemon) Threads hin.</p>
      <p>Das folgende Beispiel ermittelt durch welchen Thread die Abarbeitung eines Ereignisses (z.B. Mausklick auf Button) erfolgt:</p>
      <example id="sSwing2" caption="Ermittlung des Ereignisbehandlungssthreads" filename="sSwing2.java">
         <importText URI="../life/vorlesung/javaThreads/examples/sSwing2.java"/>
      </example>
      <p>Die Anwendung liefert bei jedem Drücken einer der beiden Schaltflächen dieselbe Ausgabe <code>Action handled by thread AWT-EventQueue-0</code>.<br/>

Bei der <em>Event Queue</em> handelt es sich um einen Thread der nebenläufig die Verarbeitung der eingetretenen Ereignisse einer GUI-basierten Swing-Applikation übernimmt. Zur Verwaltung ausgelöster, jedoch noch nicht abgearbeiteter Ereignisse wird intern eine FIFO-Warteschlange herangezogen.</p>
      <p>Am Beispiel fällt auf, daß alle Ereignisse offensichtlich durch denselben Thread verarbeitet werden. Dies läßt sich zusätzlich leicht prüfen indem künstlich Ausführungszeit der Behandlungsroutine eines Schaltflächenereignisses, etwa durch den Einbau einer Wartebedingung, erhöht wird.<br/>
In diesem Falle werden die gesamten Interaktionsmöglichkeiten der Applikation bis zum Ende der Ereignisbehandlungsroutine blockiert.<br/>
Beispiel <exRef ref="sSwing21"/> welches das vorangegangene geeignet modifiziert zeigt dies:</p>
      <example id="sSwing21" caption="Zeitintensive Ereignisbehandlung" filename="sSwing21.java">
         <importText URI="../life/vorlesung/javaThreads/examples/sSwing21.java"/>
      </example>
      <p>Aus diesem Verhalten folgt, daß zeitintensive Behandlungen -- wie etwa langwierige Initialisierungsphasen -- nicht direkt in der Ereignisbehandlungsroutine erfolgen sollten, da hierdurch die gesamte Applikation in ihrem Interaktionsverhalten negativ beeinflußt wird.<br/>
Sinnvollerweise sollten hierzu anwenderdefinierte und -kontrollierte Threads zum Einsatz kommen.</p>
      <p>
         <b>Einsatz von anwenderdefinierten Threads in Swing</b>:</p>
      <definition id="singleThreadRule" term="Single Thread Rule">
Alle Operationen, die vom Status einer visuellen Swingkomponente abhängen oder diesen verändern sollten ausschließlich innerhalb des Ereignisbearbeitungs-Threads (<em>event-dispatching thread</em>) ausgeführt werden.
</definition>
      <p>Die Definition <defRef ref="singleThreadRule"/> liefert die Begründung weshalb die Threasicherheit nur für die wenigsten Methoden der Swing API gewährleistet ist.<br/>
Konzeptionell werden Threads innerhalb der Swing-basierten Oberflächenprogrammierung ausschließlich durch Methoden der API erzeugt und gesteuert. Dem Programmierer stehen die Mechanismen der Nebenläufigkeit lediglich in Form von anwendungsspezifisch abstrahierten Klassen und Methoden (z.B. <a fixedType="JDK14" offset="java/util/Timer.html" keyword="yes">Timer</a>) zur Verfügung.<br/>
Gleichzeitig liefert die <em>Single Thread Rule</em> aber auch eine Handreichung für den Einsatz anwenderdefinierter Threads in Swing-Applikationen. Da alle durch Benutzerinteraktion implizierten Ereignisbehandlungen ausschließlich durch den Ereignisbehandlungs-Thread verarbeitet werden sollen liefert dieser auch einen natürlichen Ansatzpunkt zur Erzeugung eigener Threads.</p>
      <example id="sSwing3" caption="Ereignisbehandlung durch Threads" filename="sSwing3.java">
         <importText URI="../life/vorlesung/javaThreads/examples/sSwing3.java"/>
      </example>
      <p>Beispiel <exRef ref="sSwing3"/> erweitert das vorangegangene Beispiel in Zeile <a href="#sSwing3line30">30</a> geringfügig um die Ereignisbehandlung durch einen anwenderdefinierten Thread erfolgen zu lassen.<br/>
Hierdurch wird die tatsächliche Realisierung der Behandlung vom Aufruf der Behandlungsroutine durch den Ereingisbehandlungs-Thread entkoppelt.<br/>
Dies zeigt sich im Falle des Beispiels durch ein deutlich reaktiveres Verhalten des Gesamtapplikation obwohl immer noch unverändert fünf Sekunden für die Ereignisverarbeitung benötigt werden.<br/>
Der Preis dieses Verhaltens liegt in den zu veranschlagenden Ressourcen in Laufzeit (Threaderzeugung) und Speicher (Threadstrukturen).</p>
      <p>Gleichzeitig tritt jedoch mit der aus Anwendersicht wünschenswerten Entkopplung auch ein zusätzliches Problem zu Tage: Die realisierbare Nebenläufigkeit in der Ereignisbehandlung kann sich bei schreibenden Zugriffen auf visuelle Elemente der Oberfläche negativ auswirken, da diese Schreiboperationen generell unsynchronisiert erfolgen.</p>
      <p>Das Beispiel <exRef ref="sSwing4"/> zeigt eine fehlerhafte Ereignisbehandlung in deren Verlauf einzelne Ereignisse <gerquot>verlorengehen</gerquot>, d.h. ihre Veränderungen an der GUI durch zeitlich nachgelagerte Ereignisse überschrieben werden.</p>
      <example id="sSwing4" caption="Fehlerhafte Ereignisbehandlung durch Threads" filename="sSwing4.java">
         <importText URI="../life/vorlesung/javaThreads/examples/sSwing4.java"/>
      </example>
      <definition id="uieac" term="UI Element Access Rule">
Operationen die den Zustand visueller Elemente ändern werden ausschließlich aus dem Ereignisbehandlungs-Thread heraus ausgeführt und verwenden hierzu ausschließlich die dafür vorgesehen Methoden <a fixedType="JDK14" offset="javax/SwingUtilities.html#invokeLater(java.lang.Runnable)" keyword="yes">invokeLater</a> oder <a fixedType="JDK14" offset="javax/SwingUtilities.html#invokeAndWait(java.lang.Runnable)" keyword="yes">invokeAndWait</a>.</definition>
      <p>Diese beiden Methoden plazieren ein Ereignisobjekt in der Behandlungswarteschlage Wartschlange, wobei <code>invokeLater</code> als asynchroner Aufruf sofort nach dem Erzeugen und Einstellen des Objekts zurückkehrt, und <code>invokeAndWait</code> synchron auf die Ausführung des erzeugten Ereignisses wartet.</p>
      <p>Die beiden Methoden erwarten beide als Eingabeparameter ein Objekt welches konform zur Schnittstelle <a href="#Runnable" keyword="yes">Runnable</a> implementiert ist.<br/>
Die <code>run</code>-Methode dieses Objekts wird im Zuge der Swing-internen Ereignisbehandlung durch den Ereignisbehandlungs-Thread ausgeführt, sobald das Objekt aus der Ereigniswarteschlange entnommen wurde.</p>
      <p>Beispiel <exRef ref="sSwing5"/> zeigt die korrekte Ereignisbehandlung durch die Definition eines eigenen Ereignisobjektes ab <a href="#sSwing5line79">Zeile 79</a>.</p>
      <example id="sSwing5" caption="Korrekte nebenläufige Ereignisbehandlung" filename="sSwing5.java">
         <importText URI="../life/vorlesung/javaThreads/examples/sSwing5.java"/>
      </example>
      <subtopic name="net">Netz-spezifisches ...</subtopic>
      <p>... Hier nur zur Ergänzung zusammengestellt, da seit Java2 Version 1.4 nicht mehr originäres Thread-Thema, sondern durch die <em>New IO</em> anderweitig lösbar.</p>
      <example id="Net1" caption="Nicht nebenläufige Verarbeitung empfangenen Daten" filename="Net1.java">
         <importText URI="../life/vorlesung/javaThreads/examples/Net1.java"/>
      </example>
      <example id="Net2" caption="Einfache nebenläufige Verarbeitung von empfangenen Daten" filename="Net2.java">
         <importText URI="../life/vorlesung/javaThreads/examples/Net2.java"/>
      </example>
      <example id="TCPServer" caption="Ein einfacher TCP-Server der pro eingehender Verbindung einen Thread startet" filename="TCPServer.java">
         <importText URI="../life/vorlesung/javaThreads/examples/TCPServer.java"/>
      </example>
      <example id="TestTCPServer" caption="Einfaches Treiberprogramm" filename="TestTCPServer.java">
         <importText URI="../life/vorlesung/javaThreads/examples/TestTCPServer.java"/>
      </example>
      <topic name="definitions">Definitionsverzeichnis</topic>
      <defList/>
      <topic name="keywords">Schlagwortverzeichnis</topic>
      <keywordList/>
      <topic name="illustrations">Abbildungsverzeichnis</topic>
      <illustrationList/>
      <topic name="examples">Verzeichnis der Beispiele</topic>
      <exampleList/>
   </body>
</document>
