如何锁定 ConcurrentHashMap 中的键
How to lock on key in a ConcurrentHashMap
我正在将线程创建的对象缓存到映射中。对象的创建是昂贵的,所以我不希望多个线程 运行 创建对象,因为 put() 还没有返回。一旦线程尝试为该键创建对象,其他线程不应尝试创建该对象,即使 put 尚未完成。使用 computeIfAbsent() 是否可以在该特定键上获取 'lock' ?如果没有,还有其他方法可以实现吗?
> 使用 computeIfAbsent() 是否可以在该特定密钥上获取 'lock'?
是;每 the Javadoc for ConcurrentHashMap.computeIfAbsent(...)
:
The entire method invocation is performed atomically, so the function is applied at most once per key.
这就是方法的全部意义所在。
但是,需要明确的是,这把锁并不完全特定于那把钥匙;相反,ConcurrentHashMap
通常通过将映射拆分为多个段并为每个段锁定一个锁来工作。这允许大量并发,并且通常是最有效的方法;但您应该知道,这意味着某些线程可能会阻塞您的对象创建,即使它们实际上并未触及同一个键。
如果这对您来说是个问题,那么另一种方法是使用 ConcurrentHashMap<K, AtomicReference<V>>
之类的方法来解耦 adding 映射条目与 populating地图入口。 (AtomicReference<V>
没有 computeIfAbsent
方法,但此时您可以使用 get()
和 synchronized
的组合使用正常的双重检查锁定。)
我正在将线程创建的对象缓存到映射中。对象的创建是昂贵的,所以我不希望多个线程 运行 创建对象,因为 put() 还没有返回。一旦线程尝试为该键创建对象,其他线程不应尝试创建该对象,即使 put 尚未完成。使用 computeIfAbsent() 是否可以在该特定键上获取 'lock' ?如果没有,还有其他方法可以实现吗?
> 使用 computeIfAbsent() 是否可以在该特定密钥上获取 'lock'?
是;每 the Javadoc for ConcurrentHashMap.computeIfAbsent(...)
:
The entire method invocation is performed atomically, so the function is applied at most once per key.
这就是方法的全部意义所在。
但是,需要明确的是,这把锁并不完全特定于那把钥匙;相反,ConcurrentHashMap
通常通过将映射拆分为多个段并为每个段锁定一个锁来工作。这允许大量并发,并且通常是最有效的方法;但您应该知道,这意味着某些线程可能会阻塞您的对象创建,即使它们实际上并未触及同一个键。
如果这对您来说是个问题,那么另一种方法是使用 ConcurrentHashMap<K, AtomicReference<V>>
之类的方法来解耦 adding 映射条目与 populating地图入口。 (AtomicReference<V>
没有 computeIfAbsent
方法,但此时您可以使用 get()
和 synchronized
的组合使用正常的双重检查锁定。)