私はJavaでスレッド化するのが初めてで、いくつかのアクティブなスレッドからデータ構造にアクセスする必要があります. java.util.concurrent.ConcurrentHashMapはスレッド化に適していると聞いたことがあります。synchronized(map){}
ConcurrentHashMap にアクセスするときに使用する必要がありますか?それともロック自体を処理しますか?
5 に答える
それはロック自体を処理し、実際にはそれらにアクセスすることはできません (他のオプションはありません)。
特殊な場合に書き込みに使用できますsynchronized
が、これを行う必要があることは非常にまれです。putIfAbsent
たとえば、オブジェクトを作成するコストが高いために独自に実装する必要がある場合などです。
読み取りに syncrhonized を使用すると、同時収集を使用する目的が無効になります。
ConcurrentHashMap
すぐに使用できる以上のアトミック性を必要としない場合にのみ適しています。たとえば、値を取得し、それを使用して何かを実行し、新しい値を設定する必要がある場合、すべてアトミック操作で行う場合、これは外部ロックなしでは実現できません。
そのようなすべての場合において、コード内の明示的なロックを置き換えるものは何もなく、基本的な .xml の代わりにこの実装を使用するのは無駄HashMap
です。
短い答え: いいえ、使用する必要はありませんsynchronized(map)
。
長い答え:
- によって提供されるすべての操作
ConcurrentHashMap
はスレッドセーフであり、ロックを気にせずに呼び出すことができます - ただし、コード内で一部の操作をアトミックにする必要がある場合は、クライアント側で何らかのロックが必要になります。
いいえ、必要ありませんが、内部同期に依存する必要がある場合は、Collections.synchronizedMap
代わりに使用する必要があります。の javadoc からConcurrentHashMap
:
このクラスは、スレッド セーフに依存しているが同期の詳細には依存していないプログラムで、Hashtable と完全に相互運用できます。
実際には、データ構造全体ではなく、そのサブパーツ (一部のバケット) で同期されます。これは、ConcurrentHashMap
の反復子の一貫性が弱く、マップのサイズが不正確になる可能性があることを意味します。(しかし一方で、プット操作と取得操作は依然として一貫しており、スループットはより高くなります)
フェイル セーフ イテレータという同時実行機能以外に、concurrenthmpには注意すべき重要な機能がもう 1 つあります。反復中に put/remove のエントリセットを編集したいという理由だけで、CHMP を使用します。
もう一つです。ただし、上記の場合に ConcurrentModificationException が発生する場合があります。Collections.synchronizedMap(Map)