People may have asked this question before, but I couldn't find an
answer in my search.
I need some clarification on using Collections.synchronizedMap.
For example I have a Map
Map testMap= Collections.synchronizedMap(new HashMap());
The javadoc says I need to synchronize when I iterate thro' the map. Do
I need synchroize when I call get() and put() methods i.e. shld I do
this in the code
synchronized(testMap)
{
testMap.put();
}
synchronized(testMap)
{
testMap.get();
}
Thanks
Alan Krueger - 19 Oct 2005 03:33 GMT
> People may have asked this question before, but I couldn't find an
> answer in my search.
[quoted text clipped - 7 lines]
> I need synchroize when I call get() and put() methods i.e. shld I do
> this in the code
No, all operations on the map are synchronized. An iterator, however,
needs manual synchronization per the Javadoc.
Roedy Green - 19 Oct 2005 03:38 GMT
>The javadoc says I need to synchronize when I iterate thro' the map.
It says:
synchronizedMap
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m)
Returns a synchronized (thread-safe) map backed by the specified map.
In order to guarantee serial access, it is critical that all access to
the backing map is accomplished through the returned map.
It is imperative that the user manually synchronize on the returned
map when iterating over any of its collection views:
Map m = Collections.synchronizedMap(new HashMap());
...
Set s = m.keySet(); // Needn't be in synchronized block
...
synchronized(m) { // Synchronizing on m, not s!
Iterator i = s.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
Failure to follow this advice may result in non-deterministic
behavior.
The returned map will be serializable if the specified map is
serializable.
Parameters:
m - the map to be "wrapped" in a synchronized map.
Returns:
a synchronized view of the specified map.
I think that is pretty clear.

Signature
Canadian Mind Products, Roedy Green.
http://mindprod.com Again taking new Java programming contracts.
Thomas Hawtin - 19 Oct 2005 03:45 GMT
> For example I have a Map
> Map testMap= Collections.synchronizedMap(new HashMap());
[quoted text clipped - 12 lines]
> testMap.get();
> }
For a Map from Collections.synchronizedMap the individual methods are
already synhcronised, so no need to do it again.
The problem is that you need to make sure you have exclusive access to
the map for the entire time you are using an iterator. You don't want
some other thread to come in and modify the map whilst you are in the
middle of it. Therefore, you need to put the synchronized right around
the loop and the getting of the iterator itself, as:
synchronized (testMap) {
for (
Iterator iter = testMap.values().iterator();
iter.hasNext();
) {
Object value = iter.next();
System.out.print(value);
}
}
Or in the current version of Java:
synchronized (testMap) {
for (Object value : testMap.values()) {
System.out.print(value);
}
}
In order to minimise the length of time you have to lock held, it may be
worth your while copying the values out, and then working on them.
final Object[] values;
synchronized (testMap) {
values = testMap.values().toArray(/*new Object[0]*/);
}
for (Object value : values) {
System.out.print(value);
}
You will often find that any non-trivial use of a map will require
synchronisation around most uses, so Collections.synchronizedMap becomes
a distraction. From Java 5.0, java.util.concurrent provide some
collections that have useful additional operations and semantics. For
instance Map.putIfAbsent, allows what is typically done as multiple
operations to be done as one. CopyOnWriteArrayList allows iteration to
be done on a constant version of the list.
http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/ConcurrentMap.html#
putIfAbsent(K,
V)
http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/CopyOnWriteArrayLis
t.html#iterator()
Tom Hawtin

Signature
Unemployed English Java programmer
http://jroller.com/page/tackline/
Chris Smith - 19 Oct 2005 17:41 GMT
> I need some clarification on using Collections.synchronizedMap.
>
[quoted text clipped - 4 lines]
> I need synchroize when I call get() and put() methods i.e. shld I do
> this in the code
You need to synchronize whenever you need an atomic operation that
involve calling more than one method on the Map. So, the answer is "it
depends". If your only goal is to perform a single get or put
operation, then no you don't need the synchronized keyword. However,
let's say you've got the following code:
public void inc(Map map, Object key)
{
Integer i = (Integer) map.get(key);
if (i == null) map.put(key, new Integer(1));
else map.put("Key", new Integer(i.intValue() + 1));
}
Obviously, this could fail if something happens between the first and
second lines of code (or in several other scenarios where there's a
modification to the map between invocations of methods). You would need
to wrap this in a synchronized block to ensure that it works correctly.
So the question is this: do you want a single invocation of one method
to work, or do you want an algorithm to work properly that invokes
several methods in some sequence? synchronizedMap is sufficient for the
first purpose, but you'll need an explicit synchronized block for the
second.

Signature
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.
Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
j2eepgrmr - 20 Oct 2005 15:12 GMT
Thanks for your quick replies. The JavaDoc (1.4) wasn't clear.