2015-08-22 12 views
5

Sind Array-Elemente zwischen Arbeitern korrekt veröffentlicht?Gleichzeitige Array-Zugriff durch Executor-Service

glaube, ich habe ein großes Array (jeglicher Atomdatentyp, also nicht long oder double)

  • Ich schaffe einen Arbeiter, der das Array füllt, die ich übergeben, um es contructor,
  • I vorlegen der Arbeiter zu einem Executor, und warten Sie, bis es fertig ist (zB mit future.get()). Der Arbeiter gibt nichts zurück. Es füllt nur mein Array.
  • Dann sofort erstellen und senden Sie einen anderen Worker mit dem gleichen Array in seinem Konstruktor. Sieht es die neuesten Werte?

Mit anderen Worten, es garantiert, dass das letzte Schreiben des früheren Arbeiter geschieht also vor der ersten Lesen des nächsten Arbeiter?

Soll ich stattdessen (oder für Best Practice oder etwas) der erste Arbeiter das Array zurückgeben, obwohl die Referenz die gleiche ist wie die, die ich bereits habe?

[Bearbeiten] Einige Hintergrund: Ich verwende entweder byte Arrays oder short Arrays, die Bilder darstellen und jeweils bis zu 500.000.000 Elemente verwenden. Ich führe einfache Arithmetik für jedes Element durch.

+0

klingt wie Sie etwas werden könnte, zu tun, die besser wie ConcurrentLinkedQueue mit einer Queue-Struktur funktionieren würde. –

+0

Es ist kein Fifo. Der zweite Arbeiter benötigt einen wahlfreien Zugriff auf das Array. –

+0

fand ich so etwas wie dies in einigen Tutorial: http://www.ibm.com/developerworks/library/j-jtp03304/jsr133.gif aber ich bin nicht sicher, wie dies von globalen Variablen in dem Fall zu interpretieren. Ist * alles * mit internem RAM synchronisiert, wenn ein Thread entsperrt ist und ein anderer sperrt? Blockiert der Executor intern so oder nicht? –

Antwort

3

Von package java.util.concurrent JavaDoc verwenden können:

Die Methoden aller Klassen in java.util.concurrent und seine Subpackages erweitern diese Garantien zu einer höheren Synchronisation. Insbesondere gilt Folgendes:

durch die asynchrone Berechnung genommen Aktionen durch eine Zukunft dargestellt geschehen zuvor Aktionen im Anschluss an die Wiedergewinnung des Ergebnisses über Future.get() in einem anderen Thread.

Aktionen in einem Thread vor der Übergabe eines Runnable an einen Executor, bevor die Ausführung beginnt. Ähnliches für Callables, die einem ExecutorService übergeben werden.

Entsprechend scheint es ziemlich sicher zu einem Array von der zweiten Arbeiter in Ihrem Szenario zugreifen. Diese

+0

Ich lese gerade die Passage "Aktionen, die von der Aufgabe, die durch eine Zukunft repräsentiert wird, bevor ein anderer Thread von Future.get zurückkehrt" in Java Parallelität in der Praxis p344 (Goetz et al 2006) und dachten, ich würde meine eigene Frage beantworten, aber ich muss dich irgendwie vermisst haben. –

2

Die Elemente des Arrays sind nicht volatile, daher können sie pro Thread von der CPU zwischengespeichert werden. Es ist daher möglich, dass der erste Worker einige Array-Elemente initialisiert, aber der zweite Worker sie aufgrund von Caching nicht sieht.

Um sicherzustellen, dass die Array-Elemente sind selbst atomar, Sie eine AtomicReferenceArray

+0

Was ist mit Leistung? Als ich die ersten Arbeiter verändert ein neues Array zuzuweisen und zurückzukehren, und die Arrays über das Original in dem Haupt-Thread zu kopieren, es wurde 3 mal langsamer mit 8 Arbeiter in parallel. –

+0

Was ist falsch mit AtomicReferenceArray? – Malt

+0

Eines der Probleme ist das Gedächtnis. Mit einem 'kurzen' Array verwendet mein Programm zwei 1GiB-Arrays. Mit 'int' Arrays bekomme ich' OutOfMemoryError' (sogar mit '-Xmx8G'). Ich habe gerade ein 'AtomicReferenceArray' profiliert und es verwendet ~ 4.7 Bytes pro Element. Als nächstes, Leistung. Die Verarbeitung von Byte-Arrays dauert ~ 640 ms. Die Verarbeitung von 'kurzen' Arrays dauert ~ 1100ms. Ich werde es nicht einmal mit einem 'AtomicReferenceArray' testen, das ständig ein- und ausschaltet. –