更改 HashMap 值的成员会导致 java.util.ConcurrentModificationException

Can changing members of values of HashMap cause java.util.ConcurrentModificationException

下面的代码抛出并发修改异常,异常指向的行是for循环的第一行

private synchronized void updateAllCacheValues() {
        for (Map.Entry<Configurations, SalesConfiguration> entry : ConfigurationCache.entrySet()) {
            Configurations conf = entry.getKey();
            SalesConfiguration saleConfiguration = ConfigurationCache.get(conf);
            Map<String, String> newMap = generateKeyValueMapFromConfigurations(conf);
            lastLoadTimestamp = new Date();
            saleConfiguration.setMap(newMap, lastLoadTimestamp);
        }
        logger.debug("Successfully updated all cached configurations., cache size " + ConfigurationCache.size() + "LAST_LOAD_TIME" + lastLoadTimestamp);
    }

下面是异常跟踪

java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextNode(HashMap.java:1429)
at java.util.HashMap$EntryIterator.next(HashMap.java:1463)
at java.util.HashMap$EntryIterator.next(HashMap.java:1461)
at com.learning.java.daily.updateAllCacheValues(ConfigurationLoader.java:237)
at com.learning.java.daily.updateAllCacheValues.impl.ConfigurationLoader.loadConfigurations(ConfigurationLoader.java:156)

我猜不出是什么导致了这个异常,因为我写了一个示例测试,我正在修改 Map 值的属性,但并没有出现并发修改异常。

我认为这行是罪魁祸首。

saleConfiguration.setMap(newMap, lastLoadTimestamp);

从字面上看,ConcurrentModificationException 发生在您在遍历地图条目时更新它。您能否注释掉该行并检查您是否再收到异常?如果不是,您需要更改逻辑,以便在遍历它们时不更改映射条目。

您正在迭代条目集。因此,在迭代时不允许修改条目集值。使用 ConcurrentHashMap 而不是 HashMap。

分析如下

我们可以修改key/value的属性。但是我们不能在迭代时通过向地图添加或删除元素来修改地图。假设一个 map 有五个元素,当我们迭代它时,我们既不能向 map 添加元素,也不能从 map 删除元素。为此,我们应该使用 ConcurrentHashMap。

希望现在更清楚了。

要回答标题中的问题:,在迭代条目集时修改 HashMap 中的值 objects cannot 单独出一个ConcurrentModificationException。一定有其他事情发生了。

调用 generateKeyValueMapFromConfigurations() 或调用 saleConfiguration.setMap() 可以修改地图吗?可能是你的 ConfigurationCache 可以被其他一些并发线程修改?我知道我只是在猜测,这是我们能利用手头的信息做的最好的事情。