2017-12-28 2 views
0

Ich stieß auf das folgende Problem, wenn Sie parallele Lambdas verwenden.Lambdas im statischen Initialisierer Threadlocking

Ich habe einen statischen Initialisierungsblock in einer Klasse, die parallel über ein Array iteriert, aber ich bemerkte aus dem Stack-Trace, dass die erste Iteration korrekt abgeschlossen und Computer, jedoch alle nachfolgenden Iterationen blockieren. (Thread-Dump gibt "Warten auf:" an), was wirklich nicht hilfreich ist.

Hier ist der Code, der Thread sperrt.

public static class Test { 
    private static final Object[] objects; 

    static { 
     objects = new Object[9]; 
     IntStream.range(0, objects.length).parallel().forEach(i -> objects[i] = null); 
    } 
} 

Nachdem einige am Kopf kratzen, warum ein Array-Index Einstellen einer Gewindesicherung auf null I mit der folgenden kam verursachen würde. Ich habe ein temporäres Array innerhalb des statischen Blocks erstellt und dann am Ende das Klassen-Array zugewiesen, das das Problem behoben hat.

Hat jemand einen Einblick, warum der erste Codeblock Thread sperrt und der zweite Codeblock nicht?

+2

Ich hoffe, Ihnen ist bewusst, dass nur 'objects = new Object [9];' das tut, was Sie mit Ihrem parallelen Stream zu tun versuchen. Außerdem ist ein paralleler Strom, der neunmal eine triviale Operation ausführt, völlig übertrieben. Parallel bedeutet nicht "magisch schneller". –

+2

Warum würden Sie ihn auf null initialisieren, wenn alle Elemente null sind, nachdem Sie die Größe definiert haben? – prsvr

+0

Was meinst du "die erste Iteration wird korrekt abgeschlossen, nachfolgende Operationen blockieren"? Es gibt nur ein einziges Mal, dass dieser Code aufgerufen wird. – daniu

Antwort

4

Wenn die Klasse static initialisiert wird, enthält die JVM eine Sperre auf Klassenebene. Die Sperre verhindert, dass andere Threads auf die Klasse zugreifen, bis sie vollständig initialisiert ist.

Es gibt keine Notwendigkeit zu tun, was Sie versuchen, wie auch immer. Ein new Object[9] Array ist bereits für alle Nullen initialisiert. Ganz zu schweigen, selbst wenn es funktioniert, hat Parallelität eine Menge Overhead. Der Overhead würde den Nutzen einer Aufspaltung dieser Aufgabe über mehrere Kerne erheblich überwiegen. (Mit 9 Elementen gibt es keinen Vorteil.)

+3

Genauer gesagt, die Klasse ist gesperrt, und von anderen Threads nicht zugänglich, so dass der Lambda-Code, der läuft separate Threads ist, kann nicht zugreifen statisches Feld "Objekte". Die zweite Version des Codes greift nur aus dem Initialisierungsblock selbst auf das statische Objekt "objects" zu, weshalb es funktioniert. * Fazit: * ** Führe keine Threads von einem statischen Initialisierer aus. ** – Andreas

Verwandte Themen