繁体   English   中英

如何解决findbug调用java.util.concurrent.ConcurrentHashMap的顺序可能不是原子的

[英]How to resolve the findbug Sequence of calls to java.util.concurrent.ConcurrentHashMap may not be atomic

嗨,当我运行以下代码时,在我的项目中找到错误时,我收到了错误“对java.util.concurrent.ConcurrentHashMap的调用序列可能不是原子的”。

public static final ConcurrentHashMap<String,Vector<Person>> personTypeMap = new ConcurrentHashMap<String, Vector<Person>>();

    private static void setDefaultPersonGroup() {


        PersonDao crud = PersonDao.getInstance();
        List<Person> personDBList = crud.retrieveAll();
        for (Person person : personDBList) {
            Vector<Person> personTypeCollection = personTypeMap.get(person
                    .getGroupId());
            if (personTypeCollection == null) {
                personTypeCollection = new Vector<Person>();
                personTypeMap.put(personTypeCollection.getGroupId(),
                        personTypeCollection);
            }
            personTypeCollection.add(person);
        }
    }

我在personTypeMap.put(personTypeCollection.getGroupId(),personTypeCollection)行遇到此问题;

谁能帮助我解决问题。

复合操作在并发环境中是不安全的。

您正在执行哪些复合操作?

  • 1)您正在检查Map是否包含键的向量
  • 2)如果找不到值,则要放置一个新的Vector

因此,这是一个两步操作,很复杂,因此不安全。

他们为什么不安全?

因为它们不是原子的 考虑一下您有两个线程的情况。

考虑以下时间轴:

Thread 1 --- checks for == null -> true                                           puts a new Vector

Thread 2 ---                      checks for ==null -> true    puts a new Vector                        

ConcurrentHashMap上使用putIfAbsent()方法,为您要执行的操作提供原子解决方案。

ConcurrentHashMap#putIfAbsent()

参考文献:

该findbugs消息告诉您在多线程访问的情况下不安全:

您正在从personTypeMap获取某些personTypeMap ,检查其是否为null ,然后在这种情况下放入一个新条目。 这里有两个线程可以轻松地交织:

线程1:从地图获取
线程2:从地图获取
线程1:检查返回的值是否为空
线程1:放置新值
线程2:检查返回的值是否为空
线程2:放置新值

(仅作为示例;实际上,顺序不是给定的,关键是两个线程都为null然后对其执行操作)

您应该创建一个新条目,然后调用personTypeMap.putIfAbsent()因为这样可以保证原子性。

就您而言,您的代码应如下所示:

public static final ConcurrentHashMap<String,Vector<Person>> personTypeMap = new ConcurrentHashMap<String, Vector<Person>>();

private static void setDefaultPersonGroup() {
    PersonDao crud = PersonDao.getInstance();
    List<Person> personDBList = crud.retrieveAll();
    for (Person person : personDBList) {
        // the putIfAbsent works in the same way of your
        //previous code, but in atomic way
        Vector<Person> personTypeCollection = personTypeMap.putIfAbsent(person
                .getGroupId());
        personTypeCollection.add(person);
    }
}

暂无
暂无

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

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