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.