2つのスレッドによって読み書きされる共有ConcurrentHashMapがあります。
class Test {
ConcurrentHashMap map;
read() {
map.get(object);
}
write() {
map.put(key, object);
}
}
1つのスレッドの書き込みができるだけ早くリーダースレッドに表示されるように、マップを揮発性にする必要がありますか?
あるスレッドでのマップへの書き込みが、別のスレッドで見られない、または非常に遅れて見られる可能性はありますか? HashMapについても同じ質問です。
final
にできる場合は、それを実行してください。 final
にできない場合は、はいvolatile
にする必要があります。 volatile
はフィールド割り当てに適用され、それがfinal
でない場合、(少なくともJMMごとに)1つのスレッドによるCHMフィールドの書き込みが別のスレッドに表示されない可能性があります。繰り返しますが、これはConcurrentHashMapフィールドの割り当てであり、CHMを使用していません。
とはいえ、本当にfinal
にする必要があります。
1つのスレッドの書き込みができるだけ早くリーダースレッドに表示されるように、マップを揮発性にする必要がありますか?
CHM自体のミューテーションメソッド(put
やremove
など)を使用して書き込みを行った場合、フィールドを揮発性にしても効果はありません。すべてのメモリ可視性の保証は、CHM内で行われます。
あるスレッドでのマップへの書き込みが、別のスレッドで見られない、または非常に遅く見られる可能性はありますか? HashMapについても同じ質問です。
ConcurrentHashMap用ではありません。プレーンなHashMapを同時に使用している場合は、使用しないでください。参照: http://mailinator.blogspot.com/2009/06/beautiful-race-condition.html
volatile
は、対応する変数への読み取りおよび書き込みに「発生前のセマンティクス」を適用します。
フィールドは
volatile
と宣言できます。その場合、Javaメモリモデルは、すべてのスレッドが変数の一貫した値を参照することを保証します(§17.4)。
変数の値によって参照されるオブジェクトとは関係ありません。したがって、複数のスレッドにまたがって変数を変更しているのでない限り、変数をvolatile
にする必要はありません。
javadoc が示すように、すべてのConcurrentHashMap
メソッドはメモリバリアとして機能し、
取得は、その開始時に保留されている最後に完了した更新操作の結果を反映します。 (より正式には、特定のキーの更新操作は、更新された値を報告するそのキーの(null以外の)検索との前に発生する関係を負います。
いいえ、必要ありません。
volatile
は、変数をレジスタにキャッシュできないため、常にメモリへの「ライトスルー」になることを意味します。これは、あるスレッドの変数への変更が他のスレッドから見えることを意味します。
この場合、変数はマップへの参照です。常に同じマップを使用するため、参照を変更するのではなく、そのマップの内容を変更します。 (つまり、マップはmutableです。)これは、マップfinal
を参照できること、したがって、参照する必要があることも意味します。
ConcurrentHashMapは、通常、安全に読み取ることができるという点でHashMapとは異なりますandそれに書き込む同時に外部ロックなしで異なるスレッドから。ただし、任意の時点でサイズを信頼できるようにしたい場合、チェックアンドライト操作などを行う場合は、自分で設計する必要があります。