Findbugs - 对java.util.concurrent.ConcurrentHashMap的调用序列可能不是原子的

时间:2015-04-14 09:29:03

标签: java concurrency synchronization findbugs

我的项目中有以下代码

// Declaration

private ConcurrentHashMap<Long, ConcurrentHashMap<String, Object>> instanceSpecificBeanMap = new ConcurrentHashMap<>();

使用地图

ConcurrentHashMap<String, Object> beanMapForInstance = instanceSpecificBeanMap.get(currentInstanceId);
    Object beanObject = null;
    if(beanMapForInstance == null){
        synchronized (initLockObject) {
            beanMapForInstance = instanceSpecificBeanMap.get(currentInstanceId);
            if(beanMapForInstance == null){
                beanMapForInstance = new ConcurrentHashMap<>();
                instanceSpecificBeanMap.put(currentInstanceId, beanMapForInstance);
            }
        }
    }

我认为上面的操作是原子的,虽然findbugs将它显示为问题?我在这里错过了什么吗?

修改

beanMapForInstance仅可从此课程访问。没有其他类可以访问此变量。

另外, 目前我们正在使用 Java 7

2 个答案:

答案 0 :(得分:2)

使用putIfAbsent方法。如果给定键不存在,则精确地旨在以原子方式在地图中放置新值。

ConcurrentHashMap<String, Object> newMap = new ConcurrentHashMap<>();
ConcurrentHashMap<String, Object> beanMapForInstance = instanceSpecificBeanMap.putIfAbsent(currentInstanceId, newMap);
if (beanMapForInstance == null) {
    beanMapForInstance = newMap;
}
(... work with beanMapForInstance ...)

答案 1 :(得分:1)

您可以使用Java 8中的computeIfAbsent来简化此问题并解决问题:

ConcurrentHashMap<String, Object> beanMapForInstance = 
        instanceSpecificBeanMap.computeIfAbsent(
            currentInstanceId, 
            k -> new ConcurrentHashMap<>()  // might need explicit generics
        );