Threads Referenzoperationen sicher?

Grizzly

Top Contributor
Hallo zusammen,

heute hat mir ein Entwickler erzählt, dass der Umgang mit Referenzen in bezog auf Threads nicht sicher ist und zu Abstürzen der JVM führen kann. Habt Ihr schon einmal davon was gehört? Mir ist die Info nämlich völlig neu.

Um das Problem zu erläutern:

Ein gemeinsames Objekt (nenne ich mal sharedObject) hat eine Referenz auf ein Objekt (nenne ich mal commonObject), welches auch instanziert ist. Nun will ein Thread diese Referenz lesen (wir gehen mal davon aus, dass die Referenz public ist):
Java:
Object obj;

obj = sharedObject.commonObject;
Der zweite Thread erzeugt ein neues Objekt und überschreibt die Referenz mit der Referenz auf dieses neue Objekt:
Java:
Object obj;

obj = new Object();
sharedObject = obj;
Da der dahinter liegende Pointer (auch wenn man in Java keinen direkten Zugriff darauf hat, sind die Referenzen ja trotzdem Pointer) aus mehreren Bytes bestehen kann, kann es sein, dass der erste Thread nur einen Teil davon liest während bereits der zweite Thread diesen überschreibt. Der Pointer - oder die Referenz - , die der erste Thread dann am Ende hat, zeigt auf keine zulässige / gültige Adresse. Und beim ersten Zugriff auf diese (bspw. obj.toString()) fliegt die JVM ab. Soweit die Theorie meines Kollegen. Er hat das ganze anscheinend auf javaspecialists.eu nachgelesen. Ich konnte aber keinen entsprechenden Artikel dort finden.
 
N

nillehammer

Gast
Da hat der Kollege was falsch verstanden. Die Zuweisungsoperation ist atomar. Es kann also nicht passieren, dass ein Thread mitten in der Operation eine halb initializerte Referenz liest. Anders ist es bei folgendem:
Java:
long aLong = 64L;
Diese Zuweisung ist (laut dem hier Galileo Computing :: Java 7 - Mehr als eine Insel - 2 Threads und nebenläufige Programmierung) nicht atomar. Da kann es also sein, dass ein zweiter Thread eine halb zugewiesene Long-Variable und damit einen falschen Wert ausliest. Das meinte Dein Kollege vielleicht. Aber auch das führt nicht zum Absturz der JVM.
 
Zuletzt bearbeitet von einem Moderator:
G

Gast2

Gast
Das ändert aber nichts daran, dass man sich natürlich trotzdem um Synchronisation kümmern muss, denn Concurrency und DeadLocks können immer noch auftreten!
 

Grizzly

Top Contributor
Da hat der Kollege was falsch verstanden. Die Zuweisungsoperation ist atomar. Es kann also nicht passieren, dass ein Thread mitten in der Operation eine halb initializerte Referenz liest. Anders ist es bei folgendem:
Java:
long aLong = 64L;
Diese Zuweisung ist (laut dem hier Galileo Computing :: Java 7 - Mehr als eine Insel - 2 Threads und nebenläufige Programmierung) nicht atomar. Da kann es also sein, dass ein zweiter Thread eine halb zugewiesene Long-Variable und damit einen falschen Wert ausliest. Das meinte Dein Kollege vielleicht. Aber auch das führt nicht zum Absturz der JVM.
Okay, Galileo (bzw. der Autor) bezieht sich hier auf die primitiven Datentypen. Dass das für Referenzen auf Objekte ausdrücklich nicht gilt, steht da aber nicht, oder? ???:L

Das ändert aber nichts daran, dass man sich natürlich trotzdem um Synchronisation kümmern muss, denn Concurrency und DeadLocks können immer noch auftreten!
Okay, das ist klar. ;)
 
S

SlaterB

Gast
Okay, Galileo (bzw. der Autor) bezieht sich hier auf die primitiven Datentypen. Dass das für Referenzen auf Objekte ausdrücklich nicht gilt, steht da aber nicht, oder? ???:L
vielleicht reicht dir die empirische Tatsache, dass bisher anscheinend nie je irgendwo derartiges aufgetreten ist?
ich habe jedenfalls noch nie irgendwo von kaputten Referenzen, selbst unter beliebigen anderen Umständen, gelesen
edit:
selbst gezielter Buffer Overflow ist in Java ja relativ schwierig/ selten/ im normalen Code nicht vorhanden


andererseits ist mir auch ein halber long noch nicht begegnet, und den gibts ja anscheinend..
 
Zuletzt bearbeitet von einem Moderator:

Grizzly

Top Contributor
vielleicht reicht dir die empirische Tatsache, dass bisher anscheinend nie je irgendwo derartiges aufgetreten ist?
ich habe jedenfalls noch nie irgendwo von kaputten Referenzen, selbst unter beliebigen anderen Umständen, gelesen
edit:
selbst gezielter Buffer Overflow ist in Java ja relativ schwierig/ selten/ im normalen Code nicht vorhanden


andererseits ist mir auch ein halber long noch nicht begegnet, und den gibts ja anscheinend..

Das mit der empirischen Tatsache hat mich auch nämlich auch etwas ins grübeln gebracht. Mir ist das nämlich bisher auch nie begegnet. Aber die Geschichte mit dem long halt auch nicht. :bahnhof:
Hat nicht jemand zufällig Connections zu Oracle und könnte mal nachfragen? ;)

Was meinst mit Buffer Overflow? StackOverflowError? OutOfMemoryError? ???:L
 
M

maki

Gast
Hat nicht jemand zufällig Connections zu Oracle und könnte mal nachfragen?
Überflüssig, da Sun/Oracle die JLS herausbringt.

JLS 17.7 (Hervorhebung von mir):
17.7. Non-atomic Treatment of double and long

For the purposes of the Java programming language memory model, a single write to a non-volatile long or double value is treated as two separate writes: one to each 32-bit half. This can result in a situation where a thread sees the first 32 bits of a 64-bit value from one write, and the second 32 bits from another write.

Writes and reads of volatile long and double values are always atomic.

Writes to and reads of references are always atomic, regardless of whether they are implemented as 32-bit or 64-bit values.
Dein Kollege hatte also unrecht.

Aber wie schon oben erwähnt, müssen Zugriffe auf geteilte Ressourcen im Multithreadingbetrieb natürlich synchronisiert sein.
 
Zuletzt bearbeitet von einem Moderator:
N

nillehammer

Gast
Grizzly hat gesagt.:
Okay, Galileo (bzw. der Autor) bezieht sich hier auf die primitiven Datentypen. Dass das für Referenzen auf Objekte ausdrücklich nicht gilt, steht da aber nicht, oder?
Ok, habe es mir etwas zu bequem gemacht. In Kapitel 17.7 der Java-Spec (Chapter*17.*Threads and Locks) steht es explizit drinnen: "Writes to and reads of references are always atomic, regardless of whether they are implemented as 32-bit or 64-bit values." Dass, read/writes auf long/double nicht atomic ist, steht da auch.

[EDIT]Mist, lesen, Spec suchen, Copy und Paste hat zu lange gedauert, maki war schneller.[/EDIT]
 
M

maki

Gast
Dass, read/writes auf long/double nicht atomic ist, steht da auch.
Naja, es wird nicht garantiert dass sie Atmoic sind, dürfen es aber durchaus sein.
Ist ein Implementierungsdetail der VM, inetressant in diesem Zusammenhang ist was unter 17.7 steht:
Implementations of the Java virtual machine are encouraged to avoid splitting 64-bit values where possible. Programmers are encouraged to declare shared 64-bit values as volatile or synchronize their programs correctly to avoid possible complications.
 

Grizzly

Top Contributor

Eh, okay, war gedanklich gerade wo anders. :pfeif: Wird Zeit, dass ich Feierabend mache. ;)

Naja, es wird nicht garantiert dass sie Atmoic sind, dürfen es aber durchaus sein.
Ist ein Implementierungsdetail der VM, inetressant in diesem Zusammenhang ist was unter 17.7 steht:
Implementations of the Java virtual machine are encouraged to avoid splitting 64-bit values where possible. Programmers are encouraged to declare shared 64-bit values as volatile or synchronize their programs correctly to avoid possible complications.

Hm, klingt alles sehr schwammig. Sprich im Endeffekt wird einem geraten davon auszugehen, dass die Sachen nicht atomar sind. :(

Wobei ich nochmal darauf hinweisen möchte, dass der Abschnitt double und long behandelt. Die einzige interessante Zeile in dem Abschnitt ist:
Writes to and reads of references are always atomic, regardless of whether they are implemented as 32-bit or 64-bit values.
Nur hier wird eigentlich auf Referenzen eingegangen. Wobei es schon merkwürdig ist, dass das hier überhaupt erwähnt wird und es dafür nicht einen extra Abschnitt gibt. Immerhin ist das doch völlig losgelöst von double und long. Außer natürlich die meinen Double, Long, AtomicDouble und AtomicLong...
 

irgendjemand

Top Contributor

hmm .. sicher das es Overflows in diesem sinne in java überhaupt gibt ? da man in java weder dierekt irgendwelche pointer hat *gott sei dank* noch sonst irgendwelche (rück-)sprung-adressen manipulieren kann wäre das einzige was mir bei overflows in zusammenhang mit java einfällt ein ganz normaler "überlauf" des werte-bereiches ... aber es sollte lange nicht die schwerwiegenden konsequenzen wie z.b. in C haben ...
 
S

SlaterB

Gast
ich schrieb ja
selbst gezielter Buffer Overflow ist in Java ja relativ schwierig/ selten/ im normalen Code nicht vorhanden
also habe zumindest angedeutet dass ich wie immer von den technischen Dingen eigentlich nix verstehe ;)

Does Java have buffer overflows? - Stack Overflow

wollte nur den Begriff an sich mit reinbringen, denn das scheint mir ziemlich nahe,

und wenn es auch keine Buffer Overflows genau auf dem Wege hier mit Threads gibt,
spricht das eben für atomar sichere Referenzen
 

Grizzly

Top Contributor
Hm, kommt mir so langsam wie diese Geschichte aus Physik mit der Kaffeetasse vor: Wenn alle Elektronen der Atome der Tasse rein zufällig gerade in eine Richtung drehen, würde sich die ganze Tasse mit nahezu Lichtgeschwindigkeit in diese Richtung bewegen. Ist theoretisch möglich, wurde aber noch nie beobachtet. ;)

Naja, nachdem mein Kollegen den Artikel nicht findet, ich aber bisher auch keinen geschrieben Handfesten Gegenbeweis habe (oder ein Beispielprogramm), hängt die Sache in der Luft. :(
 
S

SlaterB

Gast
ein Gegenbeweis gegen die Behauptung deines Kollegen, ein Beweis dass es etwas NICHT gibt, ist naturgemäß auch wieder schwer ;)
(wenn der JLS-Satz nicht reicht)
 

Grizzly

Top Contributor
Okay, dann werfe ich mal etwas Neues in den Ring: Für was gibt es dann die Klasse [JAPI]AtomicReference[/JAPI]? Entweder sind Operationen auf Referenzen nicht atomar und werden es hiermit. Oder Operation sind atomar, aber über diese Klasse sind sie auch thread-safe. Wobei dann die Namensgebung etwas irreführend wäre. ???:L
 
S

SlaterB

Gast
meine erste Suche 'AtomicReference needed' führt schon zu Links, von denen ich die ersten drei hier fast posten würde, aber kann man auch selber suchen

dazu:

java.util.concurrent.atomic (Java Platform SE 7 )
The memory effects for accesses and updates of atomics generally follow the rules for volatiles, as stated in section 17.4 of The Java™ Language Specification.

get has the memory effects of reading a volatile variable.
set has the memory effects of writing (assigning) a volatile variable.
[..]

----

mag alles Standardwissen sein was du nicht hören willst, sondern neues,
aber solange du nicht jeweils dazuschreibst 'habe schon folgendes dazu gefunden und gelesen ..',
musst du immer damit rechnen, dass irgendein Neunmalkluger sowas aufzählt ;)
 

Ähnliche Java Themen

Neue Themen


Oben