ラッパークラスを使用しての違いは何であるSynchronizedMap
上、HashMap
とはConcurrentHashMap
?
それHashMap
を反復しながら(ConcurrentHashMap
)を変更できるだけですか?
ラッパークラスを使用しての違いは何であるSynchronizedMap
上、HashMap
とはConcurrentHashMap
?
それHashMap
を反復しながら(ConcurrentHashMap
)を変更できるだけですか?
回答:
同期済みHashMap
:
各メソッドは、オブジェクトレベルのロックを使用して同期されます。したがって、synchMapのgetおよびputメソッドはロックを取得します。
コレクション全体をロックすると、パフォーマンスのオーバーヘッドになります。1つのスレッドがロックを保持している間、他のスレッドはコレクションを使用できません。
ConcurrentHashMap
JDK 5で導入されました。
オブジェクトレベルでのロックはありません。ロックはより細かい単位で行われます。の場合ConcurrentHashMap
、ロックはハッシュマップバケットレベルにある可能性があります。
下位レベルのロックの効果は、同期されたコレクションでは不可能である、リーダーとライターを同時に使用できることです。これにより、スケーラビリティが大幅に向上します。
ConcurrentHashMap
ConcurrentModificationException
別のスレッドがそれを繰り返している間に、あるスレッドがそれを変更しようとした場合、はスローされません。
この記事Java 7:HashMapとConcurrentHashMap は非常によく読まれています。強くお勧めします。
ConcurrentHashMap
のsize()
結果が古くなる可能性があることは言及する価値があります。size()
「Java Concurrency in Practice」の本によれば、正確なカウントの代わりに近似値を返すことが許可されています。したがって、この方法は慎重に使用する必要があります。
短い答え:
どちらのマップも、Map
インターフェースのスレッドセーフな実装です。ConcurrentHashMap
高い並行性が期待される場合のスループットを高めるために実装されています。
ブライアンゲッツの背後にあるアイデアに関する記事ConcurrentHashMap
は、非常によく読まれています。強くお勧めします。
Map m = Collections.synchronizedMap(new HashMap(...));
docs.oracle.com/javase/7/docs/api/java/util/HashMap.html
ConcurrentHashMap
マップ全体を同期せずにスレッドセーフです。書き込みがロックで行われている間、読み取りは非常に高速に行われます。
ConcurrentHashMapとsynchronisedHashmapの両方を使用することでスレッドセーフを実現できます。しかし、それらのアーキテクチャを見ると、多くの違いがあります。
オブジェクトレベルでロックを維持します。したがって、put / getなどの操作を実行する場合は、最初にロックを取得する必要があります。同時に、他のスレッドは操作を実行できません。したがって、一度に1つのスレッドのみがこれを操作できます。したがって、ここで待機時間が増加します。ConcurrentHashMapと比較すると、パフォーマンスは比較的低いと言えます。
セグメントレベルでロックを維持します。これには16のセグメントがあり、並行性レベルはデフォルトで16に維持されます。したがって、一度に16個のスレッドがConcurrentHashMapを操作できます。さらに、読み取り操作はロックを必要としません。そのため、任意の数のスレッドがget操作を実行できます。
thread1がセグメント2でput操作を実行し、thread2がセグメント4でput操作を実行したい場合は、ここで許可されます。つまり、16個のスレッドが一度にConcurrentHashMapに対して更新(書き込み/削除)操作を実行できます。
待ち時間が少なくなるように。したがって、パフォーマンスはsynchronisedHashmapよりも比較的優れています。
どちらもHashMapの同期バージョンであり、コア機能と内部構造が異なります。
ConcurrentHashMapは、概念的には独立したHashMapとして表示できる内部セグメントで構成されています。このようなセグメントはすべて、同時実行が多い実行では、個別のスレッドによってロックできます。そのため、複数のスレッドがConcurrentHashMapからキーと値のペアを取得/出力でき、互いをブロック/待機する必要はありません。これは、より高いスループットのために実装されています。
一方
Collections.synchronizedMap()、HashMapの同期バージョンを取得し、ブロック方式でアクセスします。つまり、複数のスレッドが同時にsynchronizedMapにアクセスしようとした場合、それらは同期された方法で一度に1つずつキーと値のペアを取得/出力することができます。
ConcurrentHashMap
はlock stripping
、より高度な共有アクセスを可能にするために知られている、よりきめ細かいロックメカニズムを使用します。これにより、並行性とスケーラビリティが向上します。
またのために返されるイテレータは、ConcurrentHashMap
ある弱一貫性の代わりに、高速な手法失敗同期のHashMapで使用します。
ConcurrentHashMapは、データへの同時アクセスを可能にします。マップ全体がセグメントに分割されています。
読み取り操作、つまり get(Object key)
セグメントレベルでも同期されません。
しかし、書き込み操作、すなわち。remove(Object key), get(Object key)
セグメントレベルでロックを取得します。マップ全体の一部のみがロックされますが、他のスレッドは、ロックされたセグメントを除くさまざまなセグメントから値を読み取ることができます。
一方、SynchronizedMapでは、オブジェクトレベルでロックを取得します。すべてのスレッドは、操作(読み取り/書き込み)に関係なく、現在のスレッドを待機する必要があります。
ConcurrentHashMapとSynchronized HashMapの簡単なパフォーマンステスト
。テストフローはput
1つのスレッドで呼び出しget
、Map
同時に3 つのスレッドで呼び出しています。@trshivが言ったように、ConcurrentHashMapは、ロックなしの読み取り操作に対してより高いスループットと速度を持っています。その結果、操作時間が終了すると10^7
、ConcurrentHashMapは2x
Synchronized HashMapよりも高速になります。
SynchronizedMap
とConcurrentHashMap
スレッドセーフクラスであり、マルチスレッドアプリケーションで使用できます。これらの主な違いは、スレッドセーフを実現する方法に関するものです。
SynchronizedMap
Mapインスタンス全体をロックし、ConcurrentHashMap
Mapインスタンスを複数のセグメントに分割し、それらをロックします。
Javaドキュメントのとおり
HashtableとCollections.synchronizedMap(new HashMap())は同期されます。しかし、ConcurrentHashMapは「並行」です。
並行コレクションはスレッドセーフですが、単一の排他ロックによって制御されません。
ConcurrentHashMapの特定のケースでは、任意の数の同時読み取りと調整可能な数の同時書き込みを安全に許可します。「同期」クラスは、スケーラビリティーが低下する代わりに、単一のロックを介してコレクションへのすべてのアクセスを防止する必要がある場合に役立ちます。
複数のスレッドが共通のコレクションにアクセスすることが予想される他のケースでは、通常は「並行」バージョンが推奨されます。また、同期されていないコレクションは、コレクションが共有されていない場合、または他のロックを保持している場合にのみアクセスできる場合に適しています。
Hashtable
とはSynchronized HashMap
?