仅在需要时添加密钥时是否需要同步 ConcurrentMap?
Do I need to synchronize ConcurrentMap when adding key only if needed?
我有一个 ConcurrentMap 对象。我想写一个方法 return SomeObject 值,如果它存在,或者创建一个新的 SomeObject,把它放在 Map 中,如果它不存在,return 它。
理想情况下,我可以使用 ConcurrentMap 的 putIfAbsent(key, new SomeObject(key))
,但这意味着我每次都创建一个新的 SomeObject(key),这看起来很浪费。
所以我求助于以下代码,但不确定这是处理此问题的最佳方法:
public SomeValue getSomevalue(String key){
SomeValue result = concurrentMap.get(key);
if (result != null)
return result;
synchronized(concurrentMap){
SomeValue result = concurrentMap.get(key);
if (result == null){
result = new SomeValue(key);
concurrentMap.put(key, result);
}
return result;
}
}
Ideally, I could use ConcurrentMap's putIfAbsent(key, new SomeObject(key)), but that means that I create a new SomeObject(key) each time, which seems very wasteful.
然后使用computeIfAbsent
:
concurrentMap.computeIfAbsent(key, SomeObject::new);
将 synchronized
与 ConcurrentMap 一起使用不会阻止其他线程在 synchronized
块中间的地图上执行操作。 ConcurrentMap 不承诺使用地图的监视器进行同步,ConcurrentHashMap 和 ConcurrentSkipListMap 都不会在地图对象上同步。
请注意,ConcurrentMap 接口不保证该值只会被计算一次,或者如果键已经存在则不会计算该值。 ConcurrentHashMap 做出了这些承诺,但 ConcurrentSkipListMap 没有。
我有一个 ConcurrentMap
理想情况下,我可以使用 ConcurrentMap 的 putIfAbsent(key, new SomeObject(key))
,但这意味着我每次都创建一个新的 SomeObject(key),这看起来很浪费。
所以我求助于以下代码,但不确定这是处理此问题的最佳方法:
public SomeValue getSomevalue(String key){
SomeValue result = concurrentMap.get(key);
if (result != null)
return result;
synchronized(concurrentMap){
SomeValue result = concurrentMap.get(key);
if (result == null){
result = new SomeValue(key);
concurrentMap.put(key, result);
}
return result;
}
}
Ideally, I could use ConcurrentMap's putIfAbsent(key, new SomeObject(key)), but that means that I create a new SomeObject(key) each time, which seems very wasteful.
然后使用computeIfAbsent
:
concurrentMap.computeIfAbsent(key, SomeObject::new);
将 synchronized
与 ConcurrentMap 一起使用不会阻止其他线程在 synchronized
块中间的地图上执行操作。 ConcurrentMap 不承诺使用地图的监视器进行同步,ConcurrentHashMap 和 ConcurrentSkipListMap 都不会在地图对象上同步。
请注意,ConcurrentMap 接口不保证该值只会被计算一次,或者如果键已经存在则不会计算该值。 ConcurrentHashMap 做出了这些承诺,但 ConcurrentSkipListMap 没有。