15

別のスレッドがまだ別のセグメント/パーティションに書き込んでいる間に、ConcurrentHashMap が再ハッシュをどのように処理するのか疑問に思っています。ConcurrentHashMap がセグメントを個別にロックすることを理解している限り、たとえば、Thread2 がセグメント 2 に書き込む少し前に Thread1 がセグメント 1 に書き込みます。また、Thread1 の挿入後にテーブルのサイズを変更して再ハッシュする必要があるが、Thread2 が途中にある場合はどうなりますか?書き込み操作の?再ハッシュのためにマップ全体をロックしますか? Thread2に再ハッシュが完了するまで停止して待機するように指示するようなものはありますか? Thread2 は、テーブルのサイズ変更後にセグメント 1 に書き込む可能性があるため、正しいですか?

4

2 に答える 2

14

すべてのセグメントは個別に再ハッシュされるため、衝突は発生しません。

ConcurrentHashMap呼び出される特別なハッシュテーブルの配列ですSegments

ソースコードから

final Segment<K,V>[] segments;

/**
 * Segments are specialized versions of hash tables.  This
 * subclasses from ReentrantLock opportunistically, just to
 * simplify some locking and avoid separate construction.
 */

そして、Segmentを返すメソッドをチェックすると

final Segment<K,V> segmentFor(int hash) {
    return segments[(hash >>> segmentShift) & segmentMask];
}

したがって、put最初に呼び出してSegment使用を決定しsegmentFor、次に put を呼び出しますSegment

putソースコード

public V put(K key, V value) {
    if (value == null)
        throw new NullPointerException();
    int hash = hash(key.hashCode());
    return segmentFor(hash).put(key, hash, value, false);
}
于 2012-12-05T16:27:17.453 に答える
0

テーブル配列では、ConcurrentHashMapセグメントごとに作成されます。および に基づいて作成されたセグメントの配列concurrencyLevel

    /**
     * The per-segment table. Elements are accessed via
     * entryAt/setEntryAt providing volatile semantics.
     */
    transient volatile HashEntry<K,V>[] table;

したがって、REHASHING もセグメントのテーブルごとに行われます。したがって、これは別のセグメントのテーブルには影響しません。

これは、Array{elements} (2D) の Array{Segments} のようなものです。とても速いです:)

于 2015-03-16T10:37:01.013 に答える