Javaでvolatileキーワードを使用すると、ある種の弱い同期が得られることを知っています(可視性の更新は可能ですが、実際のロックは提供されません)。並行プログラムを実装する際に、実際のロックよりも揮発性を優先する必要がある状況はありますか?同期メカニズムとして揮発性と言っているが、C#にタグ付けされているSOについても、多少似た質問があります。
3 に答える
共有状態が単一のフィールドで構成されていて、それを割り当てるためにget-and-set構造(i++
たとえば)を使用しない場合は、volatileで十分です。ただし、揮発性の使用法のほとんどは、AtomicXxxタイプの使用に置き換えることができます(アトミックなget-and-set操作を提供します)。
つまり、ロックはプログラムをデッドロックにさらし、コードの重要な部分から並行性を排除することでパフォーマンスを妨げるため、必要のない場所ではロックを回避することをお勧めします。したがって、状況が許す限り、必ずvolatile
;に依存します。さらに必要なのがコンペアアンドスワップのようなアトミックな2段階の操作だけである場合は、を使用しますAtomicReference
。synchronized
これが唯一のオプションであるシナリオのみにフォールバックします。たとえば、重いオブジェクトを遅延初期化する必要がある場合は、二重初期化を防ぐためにロックが必要になりますが、すでに初期化されているインスタンスをフェッチしないようにする必要があります(イディオムを再確認してください)。
Volatileは、すべてのスレッドが他のスレッドによる変数の最後の書き込みを確認することを保証します。それだけです。同期は必要ありません。インスタンス変数の読み取りメソッドと書き込みメソッドの両方を同期する場合は、その変数を揮発性にする必要はありません(すべてのスレッドに最新の書き込みが表示されます)。