我想知道 ConcurrentHashMap 如何在另一个线程仍在另一个段/分区上写入时处理重新散列。据我了解,ConcurrentHashMap 独立锁定段,例如,Thread1 在 Thread2 写入段 2 之前稍微写入段 1,如果在 Thread1 插入后需要调整表大小和重新散列会发生什么情况,但 Thread2 在中间的写操作?它会锁定整个地图以进行重新散列吗?它是否有类似告诉 Thread2 停止并等到 rehash 完成的东西?因为 Thread2 可能有机会在表调整大小后最终写入 segment1,对吗?
问问题
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 on thatSegment
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 回答