繁体   English   中英

对ConcurrentHashMap的FindBugs调用序列可能不是原子的

[英]FindBugs sequence of calls to ConcurrentHashMap may not be atomic

我不明白为什么FindBug抱怨此代码

Foo obj = map.get(id);

if(obj == null) {
    obj = new Foo();
    map.put(id, obj);
}

obj.add(someObject);

第二版

Foo tmp = new Foo();
obj = map.putIfAbsent(id, tmp);
if (obj == null)
   obj = tmp

obj.add(someObject);

如果执行第二个版本,则每次都必须创建Foo对象。

Foo obj = map.get(id);

if(obj == null) {
    lock.writeLock().lock();
    try {
        obj = new Foo();
        map.put(id, obj);
    }finally {
        lock.writeLock().unlock();
    }
}

obj.add(someObject);

对于第三版,FindBugs仍然抱怨不是原子的。

它说 :

并发哈希映射的调用顺序可能不是原子的

putIfAbsent更改为putIfAbsent ,FindBugs仍然抱怨。

Findbugs观察到,一对方法调用map.get(id)map.put(id, obj)可能不是原子的,这意味着其他线程可能会在两者之间修改map

例如,另一个线程可能在这两个调用之间记录了不同的键id映射,然后当第一个线程执行其map.put()时,该映射将默默丢失。 由于您不愿意测试该键最初是否存在映射,因此此结果似乎不太可能被接受。

解决此问题的一种方法是使用ConcurrentHashMap.putIfAbsent()代替两个调用(而不仅仅是put() )。

如果其他线程在评估if ()语句时添加了带有该键的条目,则该线程将覆盖它。

您需要使用putIfAbsent ,而不是不与地图否则互动。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM