仅在需要时添加密钥时是否需要同步ConcurrentMap?

时间:2017-03-13 03:57:26

标签: java concurrency concurrenthashmap double-checked-locking

我有一个ConcurrentMap< String,SomeObject>宾语。我想编写一个方法,如果它存在则返回SomeObject值,或者创建一个新的SomeObject,将它放在Map中,如果它不存在则返回它。

理想情况下,我可以使用ConcurrentMap的putIfAbsent(key, new SomeObject(key)),但这意味着我每次都会创建一个新的SomeObject(键),这看起来非常浪费。

所以我采用了以下代码,但我不确定这是处理这个问题的最佳方法:

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;
  }
}

1 个答案:

答案 0 :(得分:4)

  

理想情况下,我可以使用ConcurrentMap的putIfAbsent(key,new SomeObject(key)),但这意味着我每次都创建一个新的SomeObject(key),这看起来非常浪费。

然后使用computeIfAbsent

concurrentMap.computeIfAbsent(key, SomeObject::new);

synchronized与ConcurrentMap一起使用不会阻止其他线程在synchronized块的中间对地图执行操作。 ConcurrentMap不承诺使用map的监视器进行同步,并且ConcurrentHashMap和ConcurrentSkipListMap都不会在地图对象上同步。

请注意,ConcurrentMap接口不保证该值仅计算一次,或者如果该键已存在则不会计算该值。 ConcurrentHashMap产生这些承诺,但ConcurrentSkipListMap没有。