2017-12-28 32 views
0

パラレルラムダを使用すると、次の問題が発生しました。静的な初期化スレッドロックのLambdas

私は静的な初期化ブロックを並列に配列を反復するクラスを持っていますが、最初の反復が正しく完了していることと、後続の反復がすべてブロックされていることがスタックトレースからわかりました。 (スレッドダンプ状態 "Waiting for:")本当に役に立たない。

スレッドがロックするコードは次のとおりです。

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); 
    } 
} 

なぜ、配列インデックスをnullに設定すると、スレッドロックが発生するのかという頭が傷つき、私は次のことを思いつきました。 私は静的ブロック内に一時的な配列を作成し、最後に問題を修正したクラス配列を割り当てました。

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

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

最初のコードブロックスレッドがロックされ、2番目のコードブロックがなぜそうでないのかについての洞察はありますか?

+2

'objects = new Object [9];はあなたの並列ストリームで何をしようとしているのか分かりません。また、9回の簡単な操作を行うための並列ストリームは完全に過剰です。パラレルは「魔法的に速い」という意味ではありません。 –

+2

サイズを定義した後に、すべての要素がnullの場合、nullに初期化するのはなぜですか? – prsvr

+0

「最初の反復が正しく完了し、後続の操作がブロックされます」という意味はどうですか?このコードが呼び出されるのは1回だけです。 – daniu

答えて

4

クラスがstaticで初期化されている場合、JVMはクラスレベルのロックを保持します。ロックは、完全に初期化されるまで、他のスレッドがクラスにアクセスするのを防ぎます。

とにかくやりたいことをする必要はありません。 new Object[9]配列はすでにすべてのNULLに初期化されています。言うまでもありませんが、たとえそれが動作したとしても、並列性には大きなオーバーヘッドがあります。オーバーヘッドは、この作業を複数のコアに分割することによるメリットよりも大幅に優れています。 (9つの要素では何のメリットもありません)

+3

具体的には、クラスはロックされ、他のスレッドからアクセスできないため、 'objects'静的フィールド。コードの第2のバージョンは、イニシャライザブロック自体から 'objects'静的フィールドにアクセスするだけであり、そのため動作します。 *結論:*静的初期化子からスレッドを実行しないでください。** – Andreas

関連する問題