当前位置: 首页 > 面试题库 >

Java并发性:HashMap和ConcurrentHashMap的“ get(Key)”性能是否相等?

姬天逸
2023-03-14
问题内容

当对底层Map不进行任何修改时(因此仅执行get()操作),get(Key)方法是否需要HashMap一个标准且ConcurrentHashMap性能相等的调用?

有背景更新:

并发是一个非常复杂的话题:我确实不需要“并发/线程安全”,但仅在卖权方面,这种情况很少发生。对于看跌期权,我可以交换Map
Associations本身(这是原子的和线程安全的)。因此,我问我正在做很多事情(并可以选择使用HashMap(创建临时Hashmap,将数据复制到新的HashMap中以及交换关联)来实现它,还是使用ConcurrentHashMap
…作为我的应用程序我想了解更多信息,这听起来很愚蠢,互联网上有太多不必要的信息,但是我认为这是很多人感兴趣的东西。有人知道ConcurrentHashMap的内部工作原理可以很好地回答这个问题。

非常感谢!


问题答案:

您可以看一下源代码。(我在看JDK 6)HashMap.get()非常简单:

public V get(Object key) {
        if (key == null)
            return getForNullKey();
        int hash = hash(key.hashCode());
        for (Entry<K,V> e = table[indexFor(hash, table.length)];
             e != null;
             e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
                return e.value;
        }
        return null;
    }

hash()进行了一些额外的移位和XOR运算,以“改善”您的哈希码。

ConcurrentHashMap.get()稍微复杂一点,但不是很多

public V get(Object key) {
    int hash = hash(key.hashCode());
    return segmentFor(hash).get(key, hash);
}

同样,hash()进行一些移位和XORing。setMentFor(int
hash)进行简单的数组查找。唯一复杂的东西是在Segment.get()中。但是,即使这看起来也不像火箭科学:

V get(Object key, int hash) {
   if (count != 0) { // read-volatile
      HashEntry<K,V> e = getFirst(hash);
      while (e != null) {
         if (e.hash == hash && key.equals(e.key)) {
            V v = e.value;
            if (v != null)
               return v;
            return readValueUnderLock(e); // recheck
          }
          e = e.next;
      }
 }
  return null;
}

获得锁的一个地方是readValueUnderLock()。评论说,这在内存模型下在技术上是合法的,但从未发生过。

总体而言,看起来两者的代码非常相似。在ConcurrentHashMap中组织得更好。因此,我认为性能足够相似。

也就是说,如果认沽期权确实非常罕见,则可以考虑实现“写时复制”类型的机制。



 类似资料:
  • 问题内容: 我有一个缓存类,其中包含一个存储缓存项。 我很好奇更改为会带来什么后果? 我会提高性能吗?此缓存是只读缓存。 最佳选择是什么?只是HashMap?缓存将按一定间隔进行填充。 问题答案: 首先,您似乎不了解关键字的作用。它确保如果声明的变量保留的 引用值发生更改,则其他线程将看到它,而不是拥有缓存的副本。它与访问线程安全无关。 鉴于此,并且您说的是只读事实,您当然不需要使用任何提供线程安

  • 问题内容: 我刚读了《清洁代码》一书,就发现了以下说法: Java很小的时候,Doug Lea撰写了开创性的书[8] Java的并行编程。他与这本书一起开发了几个线程安全的集合,这些集合后来成为该包中JDK的 一部分。该软件包中的集合对于多线程情况是安全的,并且它们表现良好。 实际上,在 几乎所有情况下 ,该 实现都比HashMap更好 。它还允许同时进行并发读写,并且它具有支持常见复合操作的方法

  • 问题内容: 我目前认为: 当您需要一种可以从中随机检索项目的结构时,请使用 当您要按顺序检索项目时(例如,使用for循环)-请使用 我通常是正确的吗?是否存在不正确的情况? 问题答案: 通常,是的,您是正确的。还有一个组合的数据结构LinkedHashMap,它提供对任意元素的快速访问以及可预测的顺序。 但是,值得注意的是,ArrayList和HashMap分别只是List和Map接口的两个实现。

  • 在一个采访问题中,我被要求解释一种情况,即使用并发哈希图与使用哈希图相比是正确的方法。在板上有两列t1和t2(对应于thread1和thread2),我应该编写一系列操作(如,等)使用concurrenthashmap与hashmap将产生预期结果。 我试图用迭代器举一个例子,但这不是面试官想要的。他在为线程1和线程2寻找一系列的放和拿操作。他说假设我们从不迭代,我们只有放和拿操作。 我查看了SO

  • 问题内容: 我真的没有得到所映射的属性的含义。请告诉我如果不使用它会如何影响。如果您能举个例子,那对我来说将非常有用。 另外,属性mappedBy和反面是否相同? 问题答案: 是的,在注解中由映射与在XML文件中执行相反的功能。 关系中始终有2个实体参与其中。 如果是一对一或一对多或多对一,则密钥将存储在其中一个实体中。将其存储在2个地方没有任何意义。 它必须告诉hibernate状态,键位于关系

  • 问题内容: 在类的equals()方法中,我使用私有实例HashMap变量进行相等性比较。但是,当比较两个对象的HashMap变量时,它们仍然显示相等。进一步的研究使我进入了链接:Link Here 。但是,它只是说HashMap1.equals(HashMap2)不起作用的原因是“显然,如果不编写自定义代码,就无法测试Java数组的相等性”。 我不明白这个原因。谁能指导我详细说明原因? 问题答案