concurrent hashMap putIfAbsent method functionality

风格不统一 提交于 2019-12-09 07:17:50

问题


I am a new bie to the world of java and exploring the concurrent hash map, while exploring the concurrent hashmap API , I discover the putifAbsent() method

public V putIfAbsent(K paramK, V paramV)
  {
    if (paramV == null)
      throw new NullPointerException();
    int i = hash(paramK.hashCode());
    return segmentFor(i).put(paramK, i, paramV, true);
  }

Now please advise what is it functionality and when do we practically require it , if possible please explain with a small simple example.


回答1:


A ConcurrentHashMap is designed so that it can be used by a large number of concurrent Threads.

Now, if you used the methods provided by the standard Map interface you would probably write something like this

  if(!map.containsKey("something")) {
      map.put("something", "a value");
  }

This looks good and seems to do the job but, it is not thread safe. So you would then think, "Ah, but I know about the synchronized keyword" and change it to this

  synchronized(map) {
      if(!map.containsKey("something")) {
          map.put("something", "a value");
      }
  }

Which fixes the issue.

Now what you have done is locked the entire map for both read and write while you check if the key exists and then add it to the map.

This is a very crude solution. Now you could implement your own solution with double checked locks and re-locking on the key etc. but that is a lot of very complicated code that is very prone to bugs.

So, instead you use the solution provided by the JDK.

The ConcurrentHashMap is a clever implementation that divides the Map into regions and locks them individually so that you can have concurrent, thread safe, reads and writes of the map without external locking.

Like all other methods in the implementation putIfAbsent locks the key's region and not the whole Map and therefore allows other things to go on in other regions in the meantime.




回答2:


ConcurrentHashMap is used when several threads may access the same map concurrently. In that case, implementing putIfAbsent() manually, like below, is not acceptable:

if (!map.containsKey(key)) {
    map.put(key, value);
} 

Indeed, two threads might execute the above block in parallel and enter in a race condition, where both first test if the key is absent, and then both put their own value in the map, breaking the invariants of the program.

The ConcurrentHashMap thus provides the putIfAbsent() operation which makes sure this is done in an atomic way, avoiding the race condition.




回答3:


Imagine we need a cache of lazy-initialized named singleton beans. Below is a ConcurrentHashMap based lock-free implementation:

ConcurrentMap<String, Object> map = new ConcurrentHashMap<>();

<T> T getBean(String name, Class<T> cls) throws Exception {
    T b1 = (T) map.get(name);
    if (b1 != null) {
        return b1;
    }
    b1 = cls.newInstance();
    T b2 = (T) map.putIfAbsent(name, b1);
    if (b2 != null) {
        return b2;
    }
    return b1;
}

Note that it solves the same problem as double-checked locking but with no locking.



来源:https://stackoverflow.com/questions/15850803/concurrent-hashmap-putifabsent-method-functionality

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!