Java并发:HashMap和ConcurrentHashMap的“get(Key)”性能相同吗?

当没有对底层Map进行修改时, get(Key)方法调用标准HashMapConcurrentHashMap的性能相同(因此只执行get()操作。)

更新背景:

并发是一个非常复杂的话题:我确实有“并发/线程安全”,但只有看跌期权,这种情况极少发生。 对于看跌期权,我可以交换地图关联本身(primefaces和线程安全)。 因此我要求我做了很多获取(并且可以选择使用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 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()执行一些额外的移位和XORing以“改进”您的哈希代码。

ConcurrentHashMap.get()有点复杂,但不是很多

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

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

 V get(Object key, int hash) { if (count != 0) { // read-volatile HashEntry 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中组织得更好一些。 所以我猜想性能足够相似。

也就是说,如果看起来非常罕见,您可以考虑实施“写入时复制”类型的机制。

你问的是错误的问题。

如果您需要并发性, 无论性能影响如何,都需要它。

正确行为的程序几乎总是比更快的程序排名更高。 我说“几乎总是”,因为可能有商业原因要发布带有错误的软件,而不是在错误得到修复之前保留。

根据ConcurrentHashMap API,检索方法没有锁定。 所以,我会说他们的表现相同。