Java ConcurrentHashMapの展開処理の詳細説明

ConcurrentHashMap の拡張プロセス中に、次の手順が実行されます。

  1. 展開条件の判定:
    ConcurrentHashMapの要素数が閾値(threshold)に達すると展開動作がトリガーされます。しきい値は、負荷率と現在のハッシュ テーブル容量に基づいて計算されます。負荷係数は、ハッシュ テーブルがどの程度満たされているかを測定する比例値です。通常、負荷係数のデフォルト値は 0.75 です。

  2. 新しいハッシュ テーブルを作成する:
    拡張プロセス中に、ConcurrentHashMap は新しい、より大容量のハッシュ テーブルを作成します。新しいハッシュ テーブルの容量は、通常、現在のハッシュ テーブルの容量の 2 倍です。同時に、新しいマスクが生成され、新しいハッシュ テーブル内の要素の位置が決定されます。

  3. セグメント化されたデータの移行:
    ConcurrentHashMap 内のデータは複数のセグメントに分散して保存されます。スケーリング中、各セグメントは個別に処理されます。セグメントごとに、その中の要素が移行されます。移行の目的は、要素を古いハッシュ テーブルから新しいハッシュ テーブル内の対応する位置に移動することです。

  4. データ移行:
    データ移行中に、各セグメントの要素が処理されます。まず、現在のセグメントのロックが取得され、移行中に他のスレッドがセグメントを変更できないようになります。次に、現在のセグメント内のリンクされたリストまたはツリー構造を走査し、その中の要素のハッシュ値を再計算し、それらを新しいハッシュ テーブル内の対応する位置に移行します。移行プロセス中に、データの正確性を保証するためにアトミック操作が使用されます。

  5. 移行を完了する:
    移行プロセス中、古いハッシュ テーブルと新しいハッシュ テーブルが共存し、古いハッシュ テーブルを同時に読み取ることができます。移行が完了すると、現在のセグメントのロックが解放され、現在のハッシュ テーブルの参照や容量など、ConcurrentHashMap の内部状態が更新されます。この時点では、新しいハッシュ テーブルが主な操作対象となり、古いハッシュ テーブルは段階的に破棄されます。

拡張プロセス全体の間、読み取り操作はロックフリーであり、同時に実行し続けることができます。移行中のデータの一貫性を確保するために、セグメントレベルのロックを取得する必要があるのは書き込み操作のみです。

ConcurrentHashMap の拡張操作はセグメントごとに実行され、ハッシュ テーブル全体はグローバルにロックされないことに注意してください。このセグメント化された移行戦略により、ConcurrentHashMap は拡張プロセス中に高い同時実行パフォーマンスを維持できます。

おすすめ

転載: blog.csdn.net/a772304419/article/details/131012692