我正在将一个线程创建的对象缓存到一个映射中。对象的创建非常昂贵,因此我不希望运行多个线程来创建对象,因为put()尚未返回。一旦线程尝试为该键创建对象,即使put尚未完成,其他线程也不应尝试创建该对象。使用computeIfAbsent()是否可以在该特定键上获取“锁”?如果没有,还有其他方法可以实现吗?
答案 0 :(得分:4)
>使用computeIfAbsent()是否可以在该特定键上获取“锁”?
是;每the Javadoc for ConcurrentHashMap.computeIfAbsent(...)
:
整个方法调用是原子执行的,因此每个键最多只能应用一次该功能。
这实际上就是方法的重点。
但是,要清楚一点,锁并不完全特定于该一把钥匙。相反,ConcurrentHashMap
通常是通过将地图分为多个段并在每个段上拥有一个锁来工作的。这允许大量并发,通常是最有效的方法。但是您应该意识到,这意味着某些线程即使实际上没有触摸相同的键也可能会阻塞对象的创建。
如果这对您来说是个问题,那么另一种方法是使用类似ConcurrentHashMap<K, AtomicReference<V>>
的方法将添加地图项与填充地图项分离。 (AtomicReference<V>
没有computeIfAbsent
方法,但是到那时,您可以结合使用get()
和synchronized
的常规双重检查锁定。)>