并发hashMap putIfAbsent方法function

我是java世界的新bie并探索并发哈希映射,在探索并发hashmap API时,我发现了putifAbsent()方法

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

现在请告知它的function是什么,我们什么时候需要它,如果可能的话请用一个简单的小例子来解释。

ConcurrentHashMap的设计使其可以被大量并发的Thread

现在,如果你使用标准Map接口提供的方法,你可能会写这样的东西

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

这看起来不错,似乎可以完成这项工作,但它不是线程安全的 。 所以你会想,“啊,但我知道synchronized关键字”并将其更改为此

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

这解决了这个问题。

现在你所做的是锁定整个地图进行读写,同时检查密钥是否存在,然后将其添加到地图中。

这是一个非常粗糙的解决方案。 现在,您可以使用双重检查锁实现自己的解决方案并重新锁定密钥等,但这是很多 非常复杂的代码,非常容易出错。

因此,您使用JDK提供的解决方案。

ConcurrentHashMap是一个聪明的实现,它将Map划分为区域并单独锁定它们,以便您可以在没有外部锁定的情况下对映射进行并发,线程安全,读取和写入。

与实现中的所有其他方法一样, putIfAbsent锁定了键的区域而不是整个Map ,因此在此期间允许其他区域继续执行其他操作。

当多个线程可以同时访问同一个映射时,使用ConcurrentHashMap。 在这种情况下,手动实现putIfAbsent(),如下所示,是不可接受的:

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

实际上,两个线程可以并行执行上面的块并进入竞争条件,其中两者都首先测试密钥是否不存在,然后两者都将它们自己的值放在映射中,从而打破了程序的不变量。

ConcurrentHashMap因此提供putIfAbsent()操作,确保以primefaces方式完成,避免竞争条件。

想象一下,我们需要一个懒惰初始化的命名单例bean的缓存。 下面是一个基于ConcurrentHashMap的无锁实现:

 ConcurrentMap map = new ConcurrentHashMap<>();  T getBean(String name, Class 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; } 

请注意,它解决了与双重检查锁定相同但没有锁定的问题。