[英]How to lock on key in a ConcurrentHashMap
我正在将一个由线程创建的对象缓存到地图中。 对象的创建是昂贵的,所以我不希望多个线程运行来创建对象,因为 put() 没有返回。 一旦一个线程尝试为该键创建对象,其他线程不应尝试创建该对象,即使 put 尚未完成。 使用 computeIfAbsent() 是否可以在该特定键上获得“锁定”? 如果没有,还有其他方法可以实现这一目标吗?
> 使用 computeIfAbsent() 是否可以在该特定键上获得“锁定”?
是的; 根据ConcurrentHashMap.computeIfAbsent(...)
的Javadoc :
整个方法调用以原子方式执行,因此每个键最多应用一次该函数。
这就是方法的全部意义所在。
但是,需要明确的是,锁并不完全特定于那把钥匙。 相反, ConcurrentHashMap
通常通过将映射拆分为多个段,并且每个段拥有一个锁来工作。 这允许大量并发,通常是最有效的方法; 但是您应该知道,这意味着某些线程可能会阻塞您的对象创建,即使它们实际上并未触及同一个键。
如果这对您来说是个问题,那么另一种方法是使用诸如ConcurrentHashMap<K, AtomicReference<V>>
之类的东西来将添加映射条目与填充映射条目分离。 ( AtomicReference<V>
没有computeIfAbsent
方法,但此时您可以使用普通的双重检查锁定与get()
和synchronized
的组合。)
进行了一些研究,但我们可能追求的是 Java ConcurrentHashMap
等效于 .NET 的.TryAdd
方法。 哪个是Java世界是:
放置如果不存在
public V putIfAbsent(K key, V value);
如果指定的键尚未与值关联,则将其与给定值关联。 这相当于:
if (!map.containsKey(key)) return map.put(key, value); else return map.get(key);
除了动作是原子执行的。
我知道必须存在原子add
操作; 只是不容易找到。 (这很奇怪,因为这就像任何人都需要打电话的第一件事)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.