なぜjava.util.concurrent.LinkedBlockingQueue
はhead
とtail
という参照を非volatile
としていますか?Javaで非揮発性のヘッドとテールのリファレンスLinkedBlockingQueue
1つのスレッドでhead
またはtail
が変更されても、別のスレッドからは見えない場合があります。
なぜjava.util.concurrent.LinkedBlockingQueue
はhead
とtail
という参照を非volatile
としていますか?Javaで非揮発性のヘッドとテールのリファレンスLinkedBlockingQueue
1つのスレッドでhead
またはtail
が変更されても、別のスレッドからは見えない場合があります。
head
およびtail
は、putLock
またはtakeLock
で保護されます。適切に同期する限り、フィールドをvolatile
と宣言する必要はありません。
あなたの質問に答えてください。フィールドが正しく同期されていれば、フィールドはvolatile
である必要はありません。
あなたが疑わしいと思うコードの一部がある場合は、私に教えてください。そうでなければ、彼らは揮発性である必要がある理由を見つけることができません。
あなたはReentrantLockの保証を意味します。それ以降のすべての読み込みと書き込みは、synchronizedブロックのようにキャッシュではなくメインメモリに起こります。したがって、別のスレッド呼び出しメソッドは常にメインメモリからヘッドを読み込みます。 – user1846749
はい、そうです。 JDKのAll Lock実装は、Java TM言語仕様のセクション17.4で説明されているように、組み込みのモニタロックによって提供されるのと同じメモリ同期セマンティクスを強制しなければなりません。 –
短い回答:いいえ、表示の問題は発生しません。
長い回答:ブロックされています。つまり、実装を聞いて、何らかの種類のsynchronized {}
ブロックがあります。変数の変更をsynchronized {}
ブロックで伝播できます。明示的なロックされている他の同期技術 -
java.util.concurrent.LinkedBlockingQueueは、頭と尾のすべての非揮発性
まずとして 参照を持つ、volatile
は、同期技術だけでなく、技術でありますしたがって、フィールド同期はロックによって処理されるので、volatile
は必ずしも必須ではありません。 John Vintの答えで説明されているように、ここでは2つのロックが使用されています。
第2に、参照型にvolatile
が使用されているとは通常ありません。追加の説明については、another SO questionを参照してください。両方の答えが素晴らしいです。
refer this question という参照型を宣言するだけでは不十分な場合があり、通常参照型にとって重要なのは、参照型のフィールドの値が実際の参照値ではなく、無効であるためです。すべてのスレッドに正しく表示される非古くなった参照は、異なるスレッド内の基礎となるオブジェクトの古いフィールド値を持つ可能性があります。
興味深い質問です。特に、そのクラスのソースコードの読み込みを開始し、ロックに関するかなりのコメントを含むものが含まれていることがわかりました。ロック方法...使用されていないのですか? – GhostCat
ロックを使用してスレッドの安全性を確保します。 –
ソースコードから、ヘッドとテールが「一時的」であることがわかります。これは「不揮発性」とは異なります。 – Paddy