• Wir präsentieren Dir heute ein Stellenangebot für einen Java Entwickler - m/w/d in Augsburg, München, Stuttgart oder Bamberg. Hier geht es zur Jobanzeige

Technische Realisierung von Atomic Datentypen

M

marco81

Mitglied
Hallo Kollegen,

was unterscheidet einen Integer von einem Atomic Integer technisch gesehen? Welche Unterschiede treten in der JVM auf?
 
1

123neu

Bekanntes Mitglied
Unterschiede sind, dass die Methoden des AtomicInteger synchronized, also threadsicher sind. Zudem kann dessen Wert nur über Methoden bezogen und gesetzt werden.

Auch ein volatiles int hat zum Beispiel keine atomare Schreiboperation, es kann also passieren dass bei der Zuweisung a=b; ein Thread einen ungültigen Wert liest der weder a noch b ist. Auch wenn das in der Praxis sehr rar vorkommt. Mit AtomicInteger wird das vermieden.
 
H

httpdigest

Top Contributor
Auch ein volatiles int hat zum Beispiel keine atomare Schreiboperation, es kann also passieren dass bei der Zuweisung a=b; ein Thread einen ungültigen Wert liest der weder a noch b ist. Auch wenn das in der Praxis sehr rar vorkommt. Mit AtomicInteger wird das vermieden.
Und auch das ist nicht korrekt.

Das Java Memory Model garantiert, dass Schreib- und Lesezugriffe auf volatile Variablen immer atomar sind, also kein Thread nur einen "Teilbereich" des Datentypen lesen kann während ein anderer Thread gerade schreibt.
Und sogar non-volatile ints sind atomar. Also, selbst, wenn man ein int nicht als volatile markiert, können solche "Zwischenzustände" nicht gelesen werden.
Nur für long und double gibt es eine explizite Unterscheidung bezüglich Atomarität: https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.7
Damit wurde der Fall mit aufgenommen, wenn man die JVM als 32-bit Prozess laufen lässt und 64-bit Werte (eben long oder double) schreibt - da ein 32-bit Prozess keine 64-bit Speicher/-Memorytransaktionen verwendet. Hier garantiert das JLS nur Atomarität auf 32-bit Teilbereichen.
Aber für als volatile markierte Variablen ist der Zugriff immer atomar (auch für longs und doubles)!

kleiner Hinweis, um das obige nicht falsch zu verstehen: Atomar bedeutet hier nicht, dass jede Operation wie etwa i++ auf einer Variablen i atomar ist, sondern direkte Lese- und Schreibzugriffe sind atomar! i++ sind drei Operationen: i lesen, inkrementieren und auf i schreiben.
 
1

123neu

Bekanntes Mitglied
Das ist eben nicht so. AtomicTypes sind nicht blockierend.
Ja stimmt, sie sind volatile, was synchronized und threadsicher gleichkommt.

Auch ein volatiles int hat zum Beispiel keine atomare Schreiboperation, es kann also passieren dass bei der Zuweisung a=b; ein Thread einen ungültigen Wert liest der weder a noch b ist. Auch wenn das in der Praxis sehr rar vorkommt. Mit AtomicInteger wird das vermieden.
Und hier muss das volatiles gestrichen werden, also:
Einfache Variablen haben zum Beispiel keine atomare Schreiboperationen, usw.

Und auch das ist nicht korrekt
Wenn du ein bisschen abwarten könntest... Alles bis auf volatiles war korrekt. 🙄
 
H

httpdigest

Top Contributor
Einfache Variablen haben zum Beispiel keine atomare Schreiboperationen, usw.
Das gilt allerdings, wie gesagt, nur für 64-bit Werte (also nur long und double). Alle kleineren Datentypen sind atomar. Immer. Auch ohne volatile.
Und praktisch gesehen sind auf 64-bit Systemen auch long und double atomar. Das Java Memory Model ist sehr "schwach" und existierende Systeme/Implementierungen sind sehr viel "robuster".
 
1

123neu

Bekanntes Mitglied
Das gilt allerdings, wie gesagt, nur für 64-bit Werte (also nur long und double). Alle kleineren Datentypen sind atomar. Immer. Auch ohne volatile.
Und praktisch gesehen sind auf 64-bit Systemen auch long und double atomar. Das Java Memory Model ist sehr "schwach" und existierende Systeme/Implementierungen sind sehr viel "robuster".
In solchen Fällen das "volatile" wegzulassen halte ich aber für unleserlichen Code. Deshalb von Anfang an richtig angewöhnen.
 
H

httpdigest

Top Contributor
Du verkennst hier aber, dass in diesem Fall "volatile" überhaupt nichts mit Atomarität zu tun hat, sondern mit Sichtbarkeit bzw. etablieren einer "happens-before" Relation. Letztlich sorgt volatile dafür, dass Caches beim Schreiben geflushed und beim Lesen invalidiert werden und, dass der JIT Compiler und die CPU keine Zugriffe/Operationen umsortieren dürfen.
Es stellt also nicht nur Atomarität sicher, sondern auch direkte Sichtbarkeit der Zugriffe.
 
M

marco81

Mitglied
Danke für eure Antworten. Ganz besonderes Dankeschön an httpdigest und 123neu die sich besonders viel Zeit genommen haben.
 

Ähnliche Java Themen

Anzeige

Neue Themen


Oben