简体   繁体   中英

Using get() after iterating over ConcurrentHashMap

I have a code snippet like this:

    private final Map<String, Information> infoMap = new ConcurrentHashMap<String, Information>();

    synchronized (infoMap) {
        for (final String nameAndVersion : infoMap.keySet()) {
            final Information info = infoMap.get(nameAndVersion);
            final String name = info.getName();
            names.add(name);
        }
    }

The question I have is: is it necessary to use the synchronized block as shown, as the operation from keySet() to get() is not atomic (and therefore the map could be updated between one call and the next, as a ConcurrentHashMap is only thread-safe for each individual call)?

Should I iterate over the EntrySet instead, to ensure the complete iterator is constructed?

I believe the synchonized block is needed if keySet() and get() is called, but I am not sure on this.

Thanks in advance for responses.

It depends on the outcome you require.

Currently, if the infoMap is modified in another thread it is quite possible for info to be null when the get is called - which would cause an NPE on the call to getName . If that is the required behaviour or you are confident that this method is the only place the Map will be modified then just synchronized is sufficient.

Using EntrySet will not side-step the issue - it will only postpone it. All that will achieve will be to ensure that if an entry is removed during iteration you will not be presented with an immediate issue - but obviously you may return data that is no longer in the map.

You should always use entrySet() method when iterating over keys and values of an HashMap. Moreover in ConcurrentHashMap, entrySet() will never throw "ConcurrentModificationException" (see Javadoc)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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