java.util.concurrent.atomic.LongAdder und DoubleAdder in Java 8

Die AtomicXXX-Klassen sind gut, wenn es nicht zu viele parallel Threads gibt, die gleichzeitig die AtomicXXX-Exemplare verändern. Der Grund ist einfach: jeder Thread warten muss, bis ein anderer Thread die Veränderung am AtomicXXX vorgenommen hat. Stehen also 100 Threads in der Schlage den AtomicXXX zu verändern, werden sie erst nacheinander abgearbeitet – das geht zwar an schnell, dennoch führt die sequenzielle Verarbeitung zu Wartesituationen.

Wenn es wirkliche viel nebenläufige Threads gibt, sind die AtomicXXX-Klassen nicht optimal und Java biete ab Java 8 zwei neue Klassen LongAdder und DoubleAdder. Ein XXXAdder sieht nach außen wie ein long/double aus (die Klassen erweitern auch Number), doch intern sind sie vielmehr eine Liste von Werten, auf die dann unterschiedliche Thread zugreifen können, ohne zu warten. Um sich das vorzustellen zu können ein Beispiel: Nehmen wir an, mehrere Threads teilen sich einen LongAdder. Ruft ein Thread add(1) auf, so führt das intern zu einem Element in einer Liste[1]. Kommt gleichzeitig add(2) am LongAdder an, muss der Thread nicht auf das Ende vom ersten add(…) warten, sondern fügt einen neuen Knoten an. Kommt später ein dritter und vierter Thread über den Weg und führt add(3) und add(4) aus, können diese ohne Warten an den ersten und zweiten existieren Knoten gehen und die Werte addieren, in den beiden internen Knoten stehen also 4 und 6. Es sind also nur so viele Knoten intern nötig, wie wirklich parallele Threads auftauchen. Eine Summation am Ende mit sum() läuft dann über die internen Knoten und summiert sie auf zu 10, was 1+2+3+4 ist.


[1] Genau genommen beim ersten Element noch in einer Variablen, die Liste beginnt erst beim zweiten Element, also beim zweiten parallelen Thread.

Ähnliche Beiträge

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert