peter
peter

Reputation: 8473

How does ConcurrentHashMap handle rehashing?

I am wondering how does ConcurrentHashMap handle rehashing while another thread is still writing on another segment/partition.

As far as I understand, ConcurrentHashMap locks the segment independently, so for example:

If Thread1 writes to the segment1 slightly before Thread2 writes to segment2, then what happens if it requires the table to resize and rehash after Thread1 insertion, but Thread2 is in the middle of the writing operation? Does it lock the whole map for rehashing? And does it have something like "tell Thread2 to stop and wait until the rehash is done"? Because Thread2 may have a chance to end up writing segment1 after the table resize, correct?

Upvotes: 17

Views: 5207

Answers (2)

Kanagavelu Sugumar
Kanagavelu Sugumar

Reputation: 19260

In ConcurrentHashMap table array is created for per-segment. And array of Segments created based on concurrencyLevel.

    /**
     * The per-segment table. Elements are accessed via
     * entryAt/setEntryAt providing volatile semantics.
     */
    transient volatile HashEntry<K,V>[] table;

So REHASHING also will be done per segment's table. So this wont affect the table of another segment.

This is something like Array{Segments} of Array{elements} (2D). So very fast :)

Upvotes: 0

Amit Deshpande
Amit Deshpande

Reputation: 19185

Every segment is separately rehashed so there is no collision.

ConcurrentHashMap is array of specialized hash tables which are called Segments

From the source code

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.
 */

And if you check the method which returns Segment

final Segment<K,V> segmentFor(int hash) {
    return segments[(hash >>> segmentShift) & segmentMask];
}

So if you call put it first determines the Segment using segmentFor and then call put on that Segment

put source code

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);
}

Upvotes: 15

Related Questions