简体   繁体   English

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

[英]Java Concurrency: Are "get(Key) for HashMap and ConcurrentHashMap equal in performance?

Are get(Key) method calls for aa standard HashMap and a ConcurrentHashMap equal in performance when no modifications happen for the underlaying Map (so only get() operations are performed.) 当没有对底层Map进行修改时, get(Key)方法调用标准HashMapConcurrentHashMap的性能相同(因此只执行get()操作。)

Update with Background: 使用背景更新:

Concurrency is quite a komplex topic: I do nead "concurrency/threadsafety" but only on puts, that happen extremely seldom. 并发性是一个非常复杂的话题:我确实“并发/线程安全”,但只有看跌期权,这种情况极少发生。 And for the puts I could swap the Map Associations itself (which is atomic and threadsafe). 对于看跌期权我可以交换地图关联本身(原子和线程安全)。 Therefore I am asking I am doing a lot of gets (and have the option to either implement it with a HashMap (create a temporary Hashmap, Copy Data into new HashMap, and swap association) or using a ConcurrentHashMap... As my App really doeas a lot of gets I want to learn more how performance is lost with both different gets. As silly this sounds, the internet has so much unnecessary information around but this is something I think could be of interest to a lot more people. So if someone knows the inner workings of ConcurrentHashMap for gets it would be great to answer the question. 因此,我要求我做了很多获取(并且可以选择使用HashMap(创建临时Hashmap,将数据复制到新的HashMap,交换关联)或使用ConcurrentHashMap实现它...作为我的应用程序真的我想了解更多关于性能如何随着不同的获取而丢失。这听起来很愚蠢,互联网上有太多不必要的信息,但我觉得这可能会引起更多人的兴趣。所以,如果有人知道ConcurrentHashMap的内部工作原理,那么回答这个问题会很棒。

Thanks very much! 非常感谢!

You're asking the wrong question. 你问的是错误的问题。

If you need concurrency, you need it no matter the performance impact. 如果您需要并发性, 无论性能影响如何,都需要它。

A correctly behaving program almost always ranks more highly than a faster program. 一个正确行为的程序几乎总是比一个更快的程序排名更高。 I say "almost always" because there may be business reasons to release software with bugs rather than holding back until the bugs are fixed. 我说“几乎总是”因为可能有商业原因要发布带有错误的软件,而不是在错误得到修复之前保留。

According to the ConcurrentHashMap API, there is no locking for retrieval methods. 根据ConcurrentHashMap API,检索方法没有锁定。 So, I'd say they are equal in performance. 所以,我会说他们的表现相同。

You could look at the source code. 你可以查看源代码。 (I'm looking at JDK 6) HashMap.get() is pretty simple: (我正在看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;
    }

Where hash() does some extra shifting and XORing to "improve" your hash code. 其中hash()执行一些额外的移位和XORing以“改进”您的哈希码。

ConcurrentHashMap.get() is a bit more complex, but not a lot ConcurrentHashMap.get()有点复杂,但不是很多

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

Again, hash() does some shifting and XORing. 同样,hash()做了一些移位和异或。 setMentFor(int hash) does a simple array lookup. setMentFor(int hash)执行简单的数组查找。 The only complex stuff is in Segment.get(). 唯一复杂的东西是在Segment.get()中。 But even that doesn't look like rocket science: 但即使这看起来不像火箭科学:

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;
}

The one place where is gets a lock is readValueUnderLock(). 获取锁定的一个地方是readValueUnderLock()。 The comments say that this is technically legal under the memory model but never known to occur. 评论说,这在内存模型下在技术上是合法的,但从未发生过。

Overall, looks like the code is pretty similar for both. 总的来说,看起来两者的代码非常相似。 Just a bit better organized in ConcurrentHashMap. 在ConcurrentHashMap中组织得更好一些。 So I'd guess that the performance is similar enough. 所以我猜测性能足够相似。

That said, if puts really are extremely rare, you could consider implementing a "copy on write" type of mechanism. 也就是说,如果看跌非常罕见,您可以考虑实施“写入时复制”类型的机制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Java ConcurrentHashMap 在性能方面优于 HashMap 吗? - Java ConcurrentHashMap is better than HashMap performance wise? Java中同步Hashmap vs ConcurrentHashMap的性能评估 - Performance evaluation of synchronized Hashmap vs ConcurrentHashMap in Java 性能 ConcurrentHashmap 与 HashMap - Performance ConcurrentHashmap vs HashMap Java控制器上的HashMap或ConcurrentHashMap? - HashMap or ConcurrentHashMap at Java Controllers? Java 并发:HashMap Vs ConcurrentHashMap 当并发线程只删除元素时 - Java Concurrency: HashMap Vs ConcurrentHashMap when concurrent threads only remove elements java ConcurrentHashMap 以构造函数为键 - java ConcurrentHashMap with constructor as key 如何在java中的concurrentHashMap中设置并发级别 - How to set concurrency level in concurrentHashMap in java 使用 ConcurrentHashMap 和同步块的 Java 并发 - Java concurrency using ConcurrentHashMap with synchronized block java Integer 的 ConcurrentHashMap 与 AtomicInteger 的 HashMap 与 AtomicInteger 的 ConcurrentHashMap - java ConcurrentHashMap of Integer vs HashMap of AtomicInteger vs ConcurrentHashMap of AtomicInteger java.util.HashMap get:密钥是否必须与存储在HashMap中的对象完全相同,或者密钥可以只是“相等” - java.util.HashMap get: does key have to be exactly the same object as what is stored in the HashMap, or can the keys just be “equal”
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM