15

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

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 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 回答