j2eepgrmr said:
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();
}
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/CopyOnWriteArrayList.html#iterator()
Tom Hawtin