web-dev-qa-db-ja.com

ConcurrentHashMap読み取りおよび書き込みロック

私はこれらに対する答えを見つけようとしていますが、GoogleまたはJava docs。

ケース1:ConcurrentHashMapで、スレッドt1はセグメントnから読み取りを行っており、同時に別のスレッドt2から読み取ります同じセグメントnに書き込むには:

質問1:これら2つの操作は次々と実行されますか、それとも同時に実行されますか?


ケース2:in ConcurrentHashMap、スレッドt1はセグメントnに書き込んでおり、同じ別のスレッドt2同じセグメントnから読み取りたい、

質問2:これら2つの操作は次々と実行されますか、それとも同時に実行されますか?

18
Learner

Javadocはあなたの両方の質問に答えると思います:

通常、取得操作(getを含む)はブロックされないため、更新操作(putおよびremoveを含む)と重複する場合があります。取得は、その開始時に保留されている最後に完了した更新操作の結果を反映します。 putAllやclearなどの集約操作の場合、同時取得は一部のエントリのみの挿入または削除を反映する場合があります。

セグメントは更新操作用です。

更新操作間で許可される同時実行性は、オプションのconcurrencyLevelコンストラクター引数(デフォルトは16)によってガイドされます。これは、内部サイジングのヒントとして使用されます。

つまり、読み取りはブロックされません(揮発性変数の読み取りとして実装されます)。同じセグメントに書き込む場合、書き込みは互いにブロックする可能性があります。

21
kan

ConcurrentHashMap Oracleドキュメントによると、

ConcurrentHashMapのコンストラクターは次のようになります。

public ConcurrentHashMap(int initialCapacity、float loadFactor、int concurrencyLevel)

したがって、上記の行は、指定された初期容量、負荷係数、同時実行レベルで新しい空のマップを作成します。ここで、ConcurrentHashMapコンストラクターから考慮する重要なパラメーター:

  • initialCapacity-初期容量。実装は、この多くの要素に対応するために内部サイジングを実行します。
  • concurrencyLevel-同時に更新されるスレッドの推定数。実装は、内部のサイズ設定を実行して、この数のスレッドに対応しようとします。

ConcurrentHashMap Apiには、次の定数があります。

  • static final int DEFAULT_INITIAL_CAPACITY = 16;
  • static final int DEFAULT_CONCURRENCY_LEVEL = 16;

concurrentHashMapコンストラクタ(またはObject)の初期容量パラメータと同時実行レベルパラメータは、デフォルトで16に設定されています。

したがって、マップ全体のロックの代わりに、ConcurrentHashMapはデフォルトで16のロックのリストを維持します(ロックの数は初期容量に等しく、デフォルトは16です)。それぞれのロックは、マップの単一のバケットをロックするために使用されます。 16個のスレッド(並行性レベルに等しいスレッドの数。デフォルトでは16)は、コレクションを同時に変更できることを示します。各スレッドは、異なるバケットで動作します。したがって、ハッシュテーブルとは異なり、ConcurrentHashMapでマップ全体をロックすることなく、あらゆる種類の操作(更新、削除、読み取り、作成)を実行します。

通常、取得操作(getを含む)はブロックしません。この場合、volatileの概念を使用します。なので、更新操作(putおよびremoveを含む)と重複する可能性があります。取得は、その開始時に保留されている最後に完了した更新操作の結果を反映します。

更新操作間で許可される同時実行性は、オプションのconcurrencyLevelコンストラクター引数(デフォルトは16)によってガイドされます。これは、内部サイジングのヒントとして使用されます。テーブルは内部的に分割されており、指定された数の同時更新を競合なしに許可しようとします。ハッシュテーブルへの配置は基本的にランダムであるため、実際の同時実行性は異なります。理想的には、テーブルを同時に変更するのと同じ数のスレッドに対応する値を選択する必要があります。必要以上に大幅に高い値を使用すると、スペースと時間が無駄になる可能性があり、大幅に低い値を使用すると、スレッドの競合が発生する可能性があります。

お役に立てば幸いです。

1
Aman Goel