News

Montag, 26. Januar 2009 | News

JAX TV: Java-Programmierung im Multicore-Zeitalter

(Link zum Artikel: http://www.it-republik.de/jaxenter/news/047030)

Der Countdown zur JAX 2009 läuft! Um Ihnen die Zeit bis zur Konferenz am 20.-24. April zu versüßen, haben wir eine Session von Angelika Langer zum Thema "Java-Programmierung im Multicore-Zeitalter" von der W-Jax 2008 als Video vorbereitet. Das Tutorial erläutert die Grundzüge des Java-Memory-Modells und Techniken für die Reduktion nichtparalleler Verarbeitungen. Beides wird für die Implementierung von Anwendungen gebraucht, die auf Multicore-oder Multiprozessorarchitekturen laufen sollen.

Angelika Langer arbeitet freiberuflich als Trainer und Consultant mit unabhängigem Kursprogramm zu anspruchsvollen Java- und C++-Themen. Sie ist Autorin zahlreicher Artikel, unter anderem einer Serie zum Java-Memory-Modell im Java Magazin.

JAX TV > Session von Angelika Langer

(Dauer: 01:04:43)


Anzeige

Kommentare

Gravatar Olaf 19.02.2009
um 00:32 Uhr
Bei der letzten Frage hat Frau Langer nicht korrekt abgewägt, ob ein Flush durch Schreiben eines 'Volatiles' nicht teurer werden kann als ein einfacher synchronised Block.

Oder was denkt Ihr?
#zitieren
Gravatar Dominik 27.02.2009
um 18:12 Uhr

Olaf:
Bei der letzten Frage hat Frau Langer nicht korrekt abgewägt, ob ein Flush durch Schreiben eines 'Volatiles' nicht teurer werden kann als ein einfacher synchronised Block.
Oder was denkt Ihr?


Sehe ich auch so. Allerdings meine ich, dass die Aussage des Fragestellers auch nicht stimmt. Wenn eine Variable in einem synchronisierten Block geschrieben wird, so muss auch alles was vor diesem Block verändert worden ist ins Memory geflusht werden. Es wird bei beiden Varianten genau gleich viel geflusht aber synchronisation ist generell teurer, daher ist in diesem Fall die Variante mit dem volatile effizienter.
#zitieren
Gravatar Armin 13.03.2009
um 20:13 Uhr
Die Frage ist eigentlich ziemlich überflüssig. Es kann keine allgemeine Antwort gegeben werden. Das Performance-Verhalten ist abhängig von der VM und der Architektur, insofern gilt: Messen! #zitieren
Gravatar Angelika Langer 17.03.2009
um 07:39 Uhr
Zur Klärung:

Der Fragesteller hat 2 Szenarien aufgemacht und wollte wissen, welches performanter abläuft. Die Frage läßt sich nicht beantworten.

Im Szenario #1 gibt es 10 Speicherstellen, die von 2 Threads konkurrierend verwendet werden; der eine Thread schreibt, der andere Thread liest. 9 der 10 Variablen sind weder volatile noch final, die 10. ist volatile und wird als letzte modifziert. Dann ist vom JMM garantiert, dass spätestens, wenn der 2. Thread die volatile Variable liest, mindestens alle Modifikation, die der 1. Thread an den 10 Objekten gemacht hat, sichtbar sind.

Im Szenario #2 gibt es ebenfalls die 10 gemeinsam verwendeten Objekte, aber keines ist volatile. Das 10. Objekt wird in einem synchronized Block modifiziert bzw. gelesen; die übrigen 9 werden vor dem synchronized Block geändert. Dann garantiert das JMM, dass spätestens, wenn der 2. Thread in seinem synchronized Block die 10. Variable liest, die Modifikation sichtbar ist, die der 1. Thread an dieser Variable gemacht hat. Vorausgesetzt, dass dasselbe Lock verwendet wurde.

Aus dieser letzten Garantie hat der Fragesteller die Frage hergeleitet, ob nicht Szenario #2 schneller sein müsse, weil ja nur eine Variable sichtbar gemacht werden muss. Dabei hat er eine Regel unterstellt, die es in JMM nicht gibt: er hat vermutet, dass der 1. Thread nicht nur _mindestens_ die Variable sichtbar macht, die er im synchronized Block modifiziert hat, sondern er hat darüber hinaus unterstellt, dass der 1. Thread _höchstens_ diese eine Variable flusht. Letzteres ist nicht garantiert, sondern reine Spekulation.

Es gibt im JMM keine Regel, die sagt, dass _nur_ die im synchronized Block modifizierten Speicherstellen geflusht werden dürfen. Die JVM kann beim Verlassen des synchronized Blocks soviel flushen, wie sie will. Und bei Architekturen mit einer hohen Cache-Kohärenz (Intel, AMD) stehen die Chancen gut, dass sie das auch tut.

Mit anderen Worten, die Frage lässt sich nicht allgemein beantworten, weil das Verhalten abhängig von der Architektur und der JVM-Implementierung ist.

Darüber hinaus sind beide Szenarien eher praxisfern. Welcher Entwickler würde 9 Variablen von mehreren Threads gemeinsam verwenden lassen, ohne in irgendeiner Form dafür zu sorgen, dass Modifikationen an den Variablen sichtbar werden? Ein solches Programm hat wenig Aussichten, ein deterministisches Verhalten an den Tag zu legen. Es ist kaum vorstellbar, dass Szenario #2 in der Praxis jemals vorkommt.

Analog bei Szenario #1: es kommt in der Praxis höchst selten vor, dass 10 Variablen, die augenscheinlich im selben Kontext modifziert und gelesen werden, keinerlei semantische Beziehung zueinander haben. An dieser Stelle werden gerne Fehler gemacht, weil eine Unabhängigkeit unterstellt wird, die bei näherem Hinsehen aber gar nicht gegeben ist. Wenn es eine Abhängigkeit gibt, dann gehören die Zugriffe synchronisiert und die Frage nach dem Vergleich mit volatile stellt sich gar nicht.

Mit anderen Worten, es war keine praxisrelevante Frage, sondern ein interessantes, akademisches Gedankenspiel - auf das es keine gescheite Antwort gibt.

Wer wirklich wissen will, welches Szenario schneller ist, muss es für seine Kombination von Hardware und JVM ausmessen - und aufpassen, dass er beim Messen keine Fehler macht.
#zitieren
zurück zum Seitenanfang