Wenn die Wirtssprache Multithreading unterstützt, muß der Garbage Collector damit klar kommen. Im einfachsten Fall werden einfach alle Threads angehalten bis auf einen, der dann den Durchlauf des Garbage Collectors ausführt.
Die Multithreadfähigkeit kann aber auch aktiv ausgenutzt werden, indem der Durchlauf in einem eigenen Thread mit niedriger Priorität passiert, und so keine extra Zeit oder Pausen für den Garbage Collector benötigt wird. Dadurch kann zumindest die Anzahl der Pausen reduziert werden, so daß nur bei besonders großen Speicheranforderungen noch eine Bereinigung mit Wartezeiten im Anwenderprogramm notwendig ist. Je nach Algorithmus erfolgt der Durchlauf entweder komplett parallel oder nur einige der Phasen. Die letzten Phasen werden in dem Fall dann durchgeführt, während das Anwederprogramm gestoppt ist, da dabei nur ein Teil der Arbeit durchgeführt wird, ist die Pausezeit immer noch deutlich geringer. Um einen Durchlauf durchzuführen während das Anwenderprogramm läuft, muß natürlich eine Synchronisation zwischen dem Anwenderprogramm und dem Garbage Collector durchgeführt werden. Auch alle Änderungen an Referenzen in bereits geprüften Objekten müssen an den Garbage Collector übermittelt werden. Dieser Zusatzaufwand verringert natürlich die Effizienz insgesamt wieder, daher ist der parallele Durchlauf des Garbage Collectors meist nur nützlich, wenn dies mit Hardwareunterstützung geschieht.
s(n) = 1 / (β + (1 - β) / n)
wurde nach
Amdahls Gesetz angefertigt, wobei von einem Anteil von β = 10%
für die nur seriell ausführbare Arbeit ausgegangen wurde. Die Anzahl
der Prozessoren n
ist auf der X-Achse eingetragen, die
entsprechende Leistungsfähigkeit auf der Y-Achse. Als theoretischer
Wert wird floor(n)
zum Vergleich ebenfalls
angezeigt.Sobald ein Mehrprozessorsystem genutzt wird, muß der Garbage Collector zumindest unterstützen, seinen Durchlauf auf entsprechend viele Threads aufzuteilen, selbst wenn er nicht parallel zum Anwenderprogramm laufen kann. Je nach verwendeten Algorithmus kann dies durchaus komplizierter sein. Beispielsweise kann ein und die selbe Speicherstelle verschiedene Werte (Referenzen) enthalten auf verschiedenen Prozessoren und damit Threads durch internes Puffern.
Da beim Anfordern von Speicher jedesmal der Thread einen geschützen Bereich (kritischer Abschnitt) betreten muß, der nur von einem Thread zu Zeit bearbeitet werden kann, kann hier ein Flaschenhals entstehen und die Skalierbarkeit durchbrochen werden. Um dies zu verhindern sollte jeder Thread sich einen eigenen gechützten Speicherbereich besorgen, auf den dieser dann ohne vorherige Synchronisation jederzeit Speicher anfordern kann. Bei generationellen Garbage Collectoren ist dies eine einfache Erweiterung, daß die jüngste Generation immer in diesen Threadlokalen Speicherbereichen angelegt wird. Während des Garbage Collector Durchlaufs kann so jeder Thread auch einfach seinen eigenen Speicherbereich scannen.
Alle Seminare - Inhaltsübersicht - Vorher: Modifikationen und Kombinationen - Nächstes: Praktische Garbage Collectoren | Seitenanfang |