I stumbled upon this article on IBM - developerworks, and the code they posted had me raise some questions:
Why is the building of the local variable
Map
wrapped within asynchronized
block? Note that they implicitly say there is only oneproducer
thread.Actually, why would this snippet require a
synchronized
block at all? Avolatile
variable should be enough for the job, as the newly created map is published only after being filled up.What is the point of only one thread
synchronizing
on a lock object?
The article mentions:
The synchronized block and the volatile keyword in Listing 1 are required because no happens-before relationship exists between the writes to the currentMap and the reads from currentMap. As a result, reading threads could see garbage if the synchronized block and the volatile keyword were not used.
And the comment in the code says:
this must be synchronized because of the Java memory model
I feel I'm dealing with multi-threading concepts outside of my understanding; I'd like someone with more expertise to point me in the right direction.
Here is the snippet taken from the article:
static volatile Map currentMap = null; // this must be volatile
static Object lockbox = new Object();
public static void buildNewMap() { // this is called by the producer
Map newMap = new HashMap(); // when the data needs to be updated
synchronized (lockbox) { // this must be synchronized because
// of the Java memory model
// .. do stuff to put things in newMap
newMap.put(....);
newMap.put(....);
}
/* After the above synchronization block, everything that is in the HashMap is
visible outside this thread */
/* Now make the updated set of values available to the consumer threads.
As long as this write operation can complete without being interrupted,
and is guaranteed to be written to shared memory, and the consumer can
live with the out of date information temporarily, this should work fine */
currentMap = newMap;
}
public static Object getFromCurrentMap(Object key) {
Map m = null;
Object result = null;
m = currentMap; // no locking around this is required
if (m != null) { // should only be null during initialization
Object result = m.get(key); // get on a HashMap is not synchronized
// Do any additional processing needed using the result
}
return(result);
}
synchronized
block though? Whether the block was there or not, the situation that the newly created map is published while others read would arise anyway...or wouldn't it? Only one thread accessing the map once at the time would require the consumers to have async
block as well, or any other lock mechanism... – Anemonevolatile
should address that issue. – Daviddavida