Collections.synchronizedMap

J

j2eepgrmr

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
 
A

Alan Krueger

j2eepgrmr said:
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

No, all operations on the map are synchronized. An iterator, however,
needs manual synchronization per the Javadoc.
 
R

Roedy Green

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.
 
T

Thomas Hawtin

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
 
C

Chris Smith

j2eepgrmr said:
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

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.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top