Java并发性:对于HashMap和ConcurrentHashMap,get(Key)是否相同? [英] Java Concurrency: Are "get(Key) for HashMap and ConcurrentHashMap equal in performance?

查看:763
本文介绍了Java并发性:对于HashMap和ConcurrentHashMap,get(Key)是否相同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

get(Key)方法调用aa标准 HashMap ConcurrentHashMap 性能相同时,对底层Map进行修改(因此只执行get()操作)。



使用背景更新:



并发是一个非常复杂的主题:我做了nead并发/线程安全,但只有在put,这非常少发生。而对于put,我可以互换地图关联本身(这是原子和线程安全)。因此,我要求我做很多获取(并且可以选择使用HashMap实现它(创建临时Hashmap,将数据复制到新的HashMap和交换关联)或使用ConcurrentHashMap ...作为我的应用程序真的doeas很多得到我想要了解更多的性能是如何失去与两个不同的获取。愚蠢的这听起来,互联网有这么多不必要的信息,但这是一个我认为可以感兴趣的更多的人,所以如果有人知道ConcurrentHashMap的内部工作原理,可以很好地回答这个问题。



非常感谢!

解决方案

你可以看源代码(我在看JDK 6)HashMap.get()很简单:



public $ get $($)
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;
}
返回null;
}

其中hash()做了一些额外的转换,并且XORing改进你的哈希代码



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

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

再次,hash()做了一些移动和XOR。 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); //重新检查
}
e = e.next;
}
}
返回null;
}

获取锁的一个地方是readValueUnderLock()。评论说,这在记忆模型下在技术上是合法的,但从来不知道会发生。



总的来说,两者的代码看起来非常相似。在ConcurrentHashMap中组织更好一点。所以我猜测这个表现是相当的。



这就是说,如果put真的非常少见,你可以考虑实现一个写上复制机制类型。


Are get(Key) method calls for a a standard HashMap and a ConcurrentHashMap equal in performance when no modifications happen for the underlaying Map (so only get() operations are performed.)

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.

Thanks very much!

解决方案

You could look at the source code. (I'm looking at JDK 6) HashMap.get() is pretty simple:

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.

ConcurrentHashMap.get() is a bit more complex, but not a lot

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

Again, hash() does some shifting and XORing. setMentFor(int hash) does a simple array lookup. The only complex stuff is in 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(). 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. 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.

这篇关于Java并发性:对于HashMap和ConcurrentHashMap,get(Key)是否相同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆