I’m using JDK 1.4…so I don’t have access to the nice concurrency stuff in 1.5+.
Consider the following class fragment:
private Map map = Collections.EMPTY_MAP;
public Map getMap() {
return map;
}
public synchronized void updateMap(Object key, Object value) {
Map newMap = new HashMap(map);
newMap.put(key, value);
map = Collections.unmodifiableMap(newMap);
}
Is it necessary to synchronize (or volatile) the map reference given that I will only be allowed to update the map via the updateMap method (which is synchronized)?
The map object will be accessed (read) in multiple threads, especially via Iterators. Knowing that Iterators will throw an exception if the back-end map’s structure is changed, I figured I would make the map unmodifiable. So as I change the structure of the map via updateMap, the existing iterators will continue working on the “old” map (which is fine for my purposes).
The side effect is, I don’t have to worry about synchronizing reads. In essense, I’m going to have a much greater magnitude of reads compared to writes. The threads that are currently iterating over the map object will continue to do so and any new threads that kick off will grab the latest map. (well, I assume it will considering erickson’s comments here – Java concurrency scenario — do I need synchronization or not?)
Can somebody comment on whether or not this idea is a good one?
Thanks!
You should use the
volatilekeyword, to ensure that Threads will see the most recentMapversion. Otherwise, without synchronization, there is no guarantee that other threads will ever see anything except the empty map.Since your
updateMap()is synchronized, each access to it will see the latest value formap. Thus, you won’t lose any updates. This is guaranteed. However, since yourgetMap()is not synchronized andmapis notvolatile, there is no guarantee that a thread will see the latest value formapunless that thread itself was the most recent thread to update the map. Use ofvolatilewill fix this.However, you do have access to the Java 1.5 and 1.6 concurrency additions. A backport exists. I highly recommend use of the backport, as it will allow easy migration to the JDK concurrency classes when you are able to migrate to a later JDK, and it allows higher performance than your method does. (Although if updates to your
mapare rare, your performance should be OK.)