I have a synchronized Map (via Collections.synchronizedMap()) that is read and updated by Thread A. Thread B accesses the Map only via Map.keySet() (read-only).
How should I synchronize this? The docs say that keySet() (for a Collections.synchronizedMap) “Needn’t be in synchronized block”. I can put Thread A’s read/write access within a synchronized block, but is that even necessary?
I guess it seems odd to me to even use a synchronized Map, or a synchronized block, if Map.keySet doesn’t need to be synchronized (according to the docs link above)…
Update: I missed that iteration of the keySet must be synchronized, even though retrieving the keySet does not require sync. Not particularly exciting to have the keySet without being able to look through it, so end result = synchronization required. Using a ConcurrentHashMap instead.
To make a truly read/write versus read/only locking
Mapwrapper, you can take a look at the wrapper theCollectionsuses forsynchronizedMap()and replace all of thesynchronizedstatements with aReentrantReadWriteLock. This is a good bit of work. Instead, you should consider switching to using aConcurrentHashMapwhich does all of the right things there.In terms of
keySet(), it doesn’t need to be in asynchronizedblock because it is already beingsynchronizedby theCollections.synchronizedMap(). The Javadocs is just pointing out that if you are iterating through the map, you need to synchronize on it because you are doing multiple operations, but you don’t need to synchronize when you are getting thekeySet()which is wrapped in aSynchronizedSetclass which does its own synchronization.Lastly, your question seemed to be implying that you don’t need to synchronize on something if you are just reading from it. You have to remember that synchronization not only protects against race conditions but also ensures that the data is properly shared by each of the processors. Even if you are accessing a
Mapas read-only, you still need to synchronize on it if any other thread is updating it.