簡體   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