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