web-dev-qa-db-ja.com

ConcurrentHashMapは内部でどのように機能しますか?

私はJavaの同時実行性に関するオラクルの公式ドキュメントを読んでいて、によって返されるCollectionの違いは何だろうと思っていました。

_public static <T> Collection<T> synchronizedCollection(Collection<T> c);
_

そして例えばを使用して

ConcurrentHashMap。私はHashMapsynchronizedCollection(Collection<T> c)を使用すると仮定しています。一般に、同期されたコレクションは基本的にHashMapの単なるデコレータであることがわかっているので、ConcurrentHashMapの内部には異なるものがあることは明らかです。これらの実装の詳細に関する情報はありますか?

編集:ソースコードが公開されていることに気付きました:ConcurrentHashMap.Java

43
Adam Arold

ConcurrentHashMapのソース を読みます。詳細はかなり複雑です。要するに

  • 独立してロックできる複数のパーティション。 (デフォルトでは16)
  • 同期の代わりにスレッドの安全性のために並行ロック操作を使用します。
  • スレッドセーフなイテレータがあります。 synchronizedCollectionのイテレータはスレッドセーフではありません。
  • 内部ロックを公開しません。 synchronizedCollectionはそうします。
42
Peter Lawrey

ConcurrentHashMapJava.util.HashTableクラスに非常に似ていますが、ConcurrentHashMapHashTablesynchronizedMapよりも優れた並行性を提供します。 ConcurrentHashMapは、マップの読み取り中にマップをロックしません。また、ConcurrentHashMapは、書き込み時にMap全体をロックしません。内部的に書き込まれるMapの部分のみをロックします。

もう1つの違いは、反復中にConcurrentModificationExceptionが変更されても、ConcurrentHashMapはConcurrentHashMapをスローしないことです。 Iteratorは複数のスレッドで使用するようには設計されていませんが、synchronizedMapConcurrentModificationExceptionをスローする場合があります

22
amicngh

これは私がそれを理解するのを助けた記事です なぜConcurrentHashMapはHashtableよりも優れており、HashMapと同じくらい良い

Hashtableはエントリへの同時アクセスを提供しますが、小さな警告があり、あらゆる種類の操作を実行するためにマップ全体がロックされます。このオーバーヘッドは通常の負荷のWebアプリケーションでは無視できますが、高負荷の場合、正当な理由がないため応答時間が遅くなり、サーバーの過負荷につながる可能性があります。

これがConcurrentHashMapのステップインです。Hashtableとほぼ同等のパフォーマンスでHashtableのすべての機能を提供します。 ConcurrentHashMapは、非常に単純なメカニズムでこれを実現します。コレクションは、マップ全体のロックの代わりに、デフォルトで16個のロックのリストを保持します。各リストは、マップの単一のバケットを保護(またはロック)するために使用されます。つまり、16個のスレッドが一度にコレクションを変更できることを意味します(それらがすべて異なるバケットで動作している限り)。実際、このコレクションによって実行される、マップ全体をロックする操作はありません。コレクションの同時実行レベル、つまりブロックせずに同時にコレクションを変更できるスレッドの数を増やすことができます。ただし、数値が大きいほど、このロックのリストを維持するオーバーヘッドが大きくなります。

15
gresdiplitude

Hashtableの「スケーラビリティの問題」は、Collections.synchronizedMap(Map)でもまったく同じように存在します。非常に単純な同期を使用します。つまり、同時に1つのスレッドのみがマップにアクセスできます。

これは、単純な挿入とルックアップがある場合はそれほど問題ではありませんが(非常に集中的に行う場合を除き)、マップ全体を反復処理する必要がある場合は大きな問題になります。 1つのスレッドがそれを行い、他のすべてのスレッドは何かを挿入または検索する場合に待機する必要があります。

ConcurrentHashMapは非常に高度な技術を使用して同期の必要性を減らし、同期なしで複数のスレッドによる並列読み取りアクセスを許可します。さらに重要なことは、同期を必要とせず、インターレーション中にMapを変更できるイテレーターを提供します(ただし、反復中に挿入された要素が返されるかどうかは保証されません)。

5
MayurB

synchronizedCollection()によって返されるオブジェクトは、すべてのメソッドがthisで同期されるオブジェクトであるため、このようなラッパーでのすべての同時操作はシリアル化されます。 ConcurrentHashMapは、競合を可能な限り低く抑えるように最適化されたきめの細かいロックを備えた真のコンカレントコンテナです。ソースコードを見ると、中身がわかります。

4
bobah

ConcurrentHashMapは、並行性を提供するConcurrentMapを実装します。深い内部のイテレータは、同期を維持する一度に1つのスレッドのみが使用するように設計されています。このマップは、並行処理で広く使用されています。

0
Manish Joshi