并发hashmap同时插入

时间:2015-08-27 14:29:56

标签: java multithreading concurrenthashmap

我已经读过,在Java中的并发hashmap中,同时插入是可能的,因为它被分成段并且为每个段采用单独的锁。 但是如果两个插入将在同一段上发生,那么这些同时发生就不会发生。 我的问题是在这种情况下会发生什么?第二次插入会等到第一次插入完成还是什么?

5 个答案:

答案 0 :(得分:3)

一般来说,您不必过于关注ConcurrentHashMap的实施方式。它只是符合ConcurrentMap的合同,这确保了可以进行并发修改。

但要回答你的问题:是的,一次插入可能会等待另一次插入完成。在内部,它使用锁来确保一个线程在等待另一个线程释放锁。内部使用的类Segment实际上继承自ReentrantLock。以下是Segmenet.put()的缩短版本:

final V put(K key, int hash, V value, boolean onlyIfAbsent) {
    HashEntry<K,V> node = tryLock() ? null : scanAndLockForPut(key, hash, value);
    V oldValue;
    try {
       // modifications
    } finally {
        unlock();
    }
    return oldValue;
}

private HashEntry<K,V> scanAndLockForPut(K key, int hash, V value) {
    // ...
    int retries = -1; // negative while locating node
    while (!tryLock()) {
        if (retries < 0) {
            // ...
        }
        else if (++retries > MAX_SCAN_RETRIES) {
            lock();
            break;
        }
        else if ((retries & 1) == 0 && (f = entryForHash(this, hash)) != first) {
            e = first = f; // re-traverse if entry changed
            retries = -1;
        }
    }
    return node;
}

这可以给你一个想法。

答案 1 :(得分:3)

ConcurrentHashMap does not block when performing retrieval operations, and there is no locking for the usual operations

大多数并发数据结构的启发式方法是首先修改后备数据结构,其中前面的数据结构对外部方法可见。然后,当修改完成时,后备数据结构成为公共数据结构,公共数据结构被推到后面。除此之外,还有更多的方法,但这是典型的合同。

答案 2 :(得分:1)

如果在同一个网段上发生2次更新,他们会互相争执,其中一次必须等待。您可以通过选择concurrencyLevel值来优化它,该值考虑将同时更新hashmap的线程数。

您可以在javadoc for the class

中找到所有详细信息

答案 3 :(得分:1)

ConcurrentHashMap包含Segment数组,而Segment又包含HashEntry数组。每个HashEntry都包含一个键,一个值和一个指向它的下一个相邻条目的指针。

但是它获得了段级别的锁定。因此你是对的。即第二次插入等到第一次插入完成

答案 4 :(得分:0)

看看javadoc for ConcurrentMap。它描述了可用于处理并发映射突变的额外方法。