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

use*_*216 5 java concurrency map

当底层 Map 没有发生任何修改时,get(Key)方法调用是否符合标准HashMapConcurrentHashMap性能相同(因此只执行 get() 操作。)

更新背景:

并发是一个相当复杂的话题:我确实需要“并发/线程安全”,但只在看跌期权上,这种情况很少发生。对于 puts,我可以交换 Map Associations 本身(这是原子和线程安全的)。因此我问我正在做很多获取(并且可以选择使用 HashMap 实现它(创建一个临时 Hashmap,将数据复制到新的 HashMap,并交换关联)或使用 ConcurrentHashMap ......就像我的应用程序一样doeas很多gets我想更多地了解两种不同gets的性能如何损失。这听起来很愚蠢,但互联网上有太多不必要的信息,但我认为这是更多人可能感兴趣的东西。所以如果有人知道 ConcurrentHashMap 的内部工作原理,回答这个问题会很棒。

非常感谢!

use*_*300 2

你可以看一下源代码。(我正在查看 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;
    }
Run Code Online (Sandbox Code Playgroud)

hash() 会进行一些额外的移位和异或来“改进”您的哈希代码。

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

public V get(Object key) {
    int hash = hash(key.hashCode());
    return segmentFor(hash).get(key, hash);
}
Run Code Online (Sandbox Code Playgroud)

同样,hash() 会进行一些移位和异或运算。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;
}
Run Code Online (Sandbox Code Playgroud)

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

总的来说,看起来两者的代码非常相似。在 ConcurrentHashMap 中组织得更好一些。所以我猜性能足够相似。

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