并发hashmap size()方法的复杂性

时间:2012-05-25 12:44:25

标签: java concurrency java.util.concurrent concurrenthashmap

我想知道在size()上调用的ConcurrentHashMap方法与通常的HashMap的size()方法的复杂性是否相同。

5 个答案:

答案 0 :(得分:6)

JDK 8 ConcurrentHashMap.size()的新实现使用了一种很酷的算法,它们可以从LongAdder复制粘贴。

实际上,ConcurrentHashMap.size()的复杂性几乎是不变的(" O(1)"用书呆子语言),与HashMap.size()相比,实时成本可以忽略不计。别相信我?打开我的基本test project并自己跑步。我没有在我当前的机器上安装JDK 7,与Java 1.8相比,使用Java 1.7获得时间成本反馈会很酷。

答案 1 :(得分:5)

不是。在我的JDK版本中,HashMap.size()具有O(1)复杂度,而ConcurrentHashMap.size() 在最佳情况下必须迭代这些段。在最坏的情况下,它将锁定所有段,这在多线程场景中可能是相当昂贵的操作。

当然,更快是一个完全不同的问题。答案很大程度上取决于访问地图的线程数量,以及它们正在做什么。

答案 2 :(得分:5)

size()HashMap的复杂性为O(1),因为大小存储在字段中。如果我们在size()上查看ConcurrentHashMap的实现,我们会看到它更大(> O(1))

参考(openjdk-6)

答案 3 :(得分:0)

ConcurrentHashMap中size()方法的复杂性本质上是一个O(N)操作(主要根据段的数量而变化),如您在源代码中看到的那样。 HashMap是一个O(1)操作。

/**
 * Returns the number of key-value mappings in this map.  If the
 * map contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
 * <tt>Integer.MAX_VALUE</tt>.
 *
 * @return the number of key-value mappings in this map
 */
public int size() {
    final Segment<K,V>[] segments = this.segments;
    long sum = 0;
    long check = 0;
    int[] mc = new int[segments.length];
    // Try a few times to get accurate count. On failure due to
    // continuous async changes in table, resort to locking.
    for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) {
        check = 0;
        sum = 0;
        int mcsum = 0;
        for (int i = 0; i < segments.length; ++i) {
            sum += segments[i].count;
            mcsum += mc[i] = segments[i].modCount;
        }
        if (mcsum != 0) {
            for (int i = 0; i < segments.length; ++i) {
                check += segments[i].count;
                if (mc[i] != segments[i].modCount) {
                    check = -1; // force retry
                    break;
                }
            }
        }
        if (check == sum)
            break;
    }
    if (check != sum) { // Resort to locking all segments
        sum = 0;
        for (int i = 0; i < segments.length; ++i)
            segments[i].lock();
        for (int i = 0; i < segments.length; ++i)
            sum += segments[i].count;
        for (int i = 0; i < segments.length; ++i)
            segments[i].unlock();
    }
    if (sum > Integer.MAX_VALUE)
        return Integer.MAX_VALUE;
    else
        return (int)sum;
}

答案 4 :(得分:0)

这是一个无关紧要的问题,因为在同时可变的结构上调用size()是一件毫无意义的事情。所有它会告诉你的是的大小,除了记录它之外,你实际上无法对这些信息做任何事情。

如果您尝试使用size()而不锁定结构,则会出现竞争条件。