我想知道ConcurrentHashMap如何处理rehashing而另一个线程仍在另一个段/分区上写入。据我所知,ConcurrentHashMap独立锁定段,例如, 在Thread2写入segment2之前,Thread1稍微写入segment1,如果在Thread1插入后需要表调整大小并重新散列,会发生什么情况,但是Thread2正处于写入操作的中间?它会锁定整个地图以进行重组吗?它是否有类似告诉Thread2停止并等到rehash完成?因为Thread2可能有机会在表调整大小后最终写出segment1,对吗?
答案 0 :(得分: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
然后再调用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);
}
答案 1 :(得分: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}。非常快:)