ConcurrentHashMap如何处理rehashing?

时间:2012-12-05 16:24:38

标签: java multithreading java.util.concurrent concurrenthashmap

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

2 个答案:

答案 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}。非常快:)