Synchronisation

aus www.iwiki.de, der freien Wissensdatenbank

Synchronisation ist eine Festlegung der Zugriffsregeln der Threads auf gemeinsame Objekte. Zweck der Synchronisation ist der gegenseitiger Ausschluß und das Vermeiden von gleichzeitigen Objektzugriffen, da die kritisch sein können. Nicht ausreichend konzepierte Synchronisation kann zu Deadlock führen.


Oft werden die Threads auf Bedingungen synchronisiert. Man spricht in diesem Fall von der Synchronisation auf Bedingungen. Bei Ausführung eines synchronized Anweisungsblocks oder einer synchronized Methode kann ein Thread auf eine Bedingung stoßen. Die weitere Ausführung macht nur dann Sinn, wenn die Bedingung eingetreten ist.

Für die Synchronisation auf Bedingungen gibt es zwei Lösungsansätze. Der erste Ansatz ist das sogenannte Polling/Busy Waiting ("beschäftigtes Warten"). Bei dieser Methode wird die Bedingung in einer Schleife ständig überprüft.

Dabei ist wichtig, dass der Thread nicht ständig beschäftigt ist. Nach jeder Überprüfung der Bedingung, wo die gewünschte Bedingung noch nicht eingetreten ist, sollte man die Kontrolle über das Objekt abgeben. Hier kann man die sogenannte sleep() Methode anwenden. Sonst würde die Bedingung auch nie ändern und würde zu einem Deadlock führen.

Der zweite Ansatz ist die sogenannte Ereigniswarteschlange. Jedes Monitor-Objekt hat eine Ereigniswarteschlange, in der Threads auf das Eintreten einer Bedingung warten können. Hier wird der Thread in der Ereigniswarteschlange des Monitor-Objekts blockiert, bis das Änderungsereignis eintritt. Hier kann man die sogenannte wait() Methode anwenden.

Dabei ist wichtig, dass der blockierte Thread den Lock auf das Monitor-Objekt freigibt. Er wird durch einen anderen Thread erst dann aktiviert, wenn das Änderungsereignis eintritt. Die Änderungsbedingung wird in einer while-Schleife überprüft. Die notify() Methode aktiviert irgendeinen in der Ereigniswarteschlange des Monitor-Objekts verzögerten Thread.

Die notifyAll() Methode aktiviert alle in der Ereigniswarteschlange des Monitorobjekts verzögerten Threads. Die Methoden notify() und notifyAll() haben aber keine Wirkung, wenn die Ereigniswarteschlange leer ist. Die Methode notifyAll() ist zwar manchmal ineffizient, aber nie falsch.

Tritt ein notify() oder notifyAll() vor der Verzögerung des Threads durch wait() auf, so geht das Signal verloren. In diesem Fall spricht man von dem sogenannen Lost Signal ("verlorenes Signal"). "Lost Signals" können immer dann auftreten, wenn wait() und notify() oder notifyAll() nicht an eine eindeutige Zustandsvariable gekoppelt sind. Das kann aber auch zu Fehlern führen, wenn dieser Fall im Programm nicht berücksichtigt wird.