Der unbekannte Monitor
« | 27 Oct 2018 | »Fast kein Programmierer weiß heute mehr was ein Monitor ist.
Natürlich meine ich damit nicht den Bildschirm, sondern ein Synchronisierungsobjekt, das in vielen Sprachen und Betriebssystemen vorhanden ist.
Ausgerechnet die Windows API hat auf dieses Konstrukt bis zu NT 6 (auch als Vista bekannt) verzichtet.
In Java und C# hingegen ist quasi alles ein Monitor … nur nutzt diesen fast niemand.
In POSIX baut man sich einen Monitor aus einem pthread_mutex und einer pthread_cond -ition zusammen.
Die Veröffentlichung einer Veränderung läuft dann so ab:
- Zuerst sperrt man den Mutex
- Dann verändert man eine geteilten Variableninhalt
- Nun signalisiert man die Veränderung an alle darauf Wartenden über die Condition
- Und abschließend gibt man die Mutex-Sperre wieder frei.
Nachtrag: Eine bessere Performance bietet:
Sperren-Setzen-Entsperren-Signal
Doch wenn manSperren-Setzen-Signal-Entsperren
nutzt, geht einem die Statusänderung seltener oder nie verloren, wenn zwei Threads gleichzeitig signalisieren wollen, weil die Signale selbst synchronisiert werden.
Die Gegenseite wartet auf das Signal wie folgt.
- Zuerst sperrt man den Mutex
- Dann wird eine Schleife eröffnet:
- Man wartet auf das Signal
- Man prüft den Inhalt der geteilten Variablen
- Ist der Inhalt nicht relevant wiederholt man die Schleife
- Ist der Inhalt relevant beendet man die Schleife
- Abschließend gibt man die Mutex-Sperre wieder frei.
Das ‘Signalisieren’ und das ‘Warten auf ein Signal’ hat einen Vorteil:
Das Betriebssystem achtet darauf, dass dieser Vorgang gemeinsam mit
dem Freigeben und erneutem Sperren des Mutex vonstatten geht …
und zwar aus der Sicht des User-Prozesses als ‘atomar’.
Es gibt also keinen Zwischenzustand, wo der Mutex vor oder nach dem Signal verändert wird.
Die Windows API bis Windows XP und Server 2003 hat dieses Feature nicht und ihre eigenen Signal-Event” können daher genau in solche Zwischenzustände laufen.
Aber Freunde: Jetzt kommt’s!
Jedes Java Objekt ererbt sich von der Object-Basisklasse die Methoden notify und wait. Gemeinsam mit synchronized kann man also aus JEDEM Objekt einen Monitor machen.
Und in C# sieht das ganz ähnlich aus. Hier haben wir die System.Threading.Monitor Klasse, die jedes object monitoren kann … und das auch schon seit dotNet 1.0.
Aber obwohl Java und C# quasi voller potentieller Monitoren sind, habe ich diese Programmierform in freier Wildbahn nur selten angetroffen.
Und wegen meiner Vergangenheit mit der WinAPI schaffe ich mir auch oft eigene Synchronisierungskonstrukte … eigentlich ist das ja dumm, weil Monitore wegen ihrer Unterstützung im OS eine hohe Effizienz und Zuverlässigkeit aufweisen.
Fazit
Lasset uns mehr Monitore nutzen!
Früher (vor Vista) war halt doch nicht alles besser ;)