并发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; }
请注意,它解决了与双重检查锁定相同但没有锁定的问题。
- ConcurrentHashMap构造函数参数?
- ConcurrentHashMap锁定
- 为什么无法锁定ConcurrentHashMap进行独占访问?
- 使用ConcurrentHashMap,何时需要同步?
- ConcurrentHashMap返回一个弱一致的迭代器,为什么我们应该使用它呢?
- Java ConcurrentHashMap不是线程安全的..是吗?
- 需要简单解释“锁定条带化”如何与ConcurrentHashMap一起使用
- 从理论上讲,ConcurrentHashMap的Segment和HashMap的桶之间有什么区别?
- ConcurrentHashMap jdk 8使用TreeNodes而不是List ..为什么?