简体   繁体   中英

Does map need to be synchronized if for each entry only one thread is accessing it?

I have a map. Lets say:

Map<String, Object> map = new HashMap<String, Object>();

Multiple threads are accessing this map, however each thread accesses only its own entries in the map. This means that if thread T1 inserts object A into the map, it is guaranteed that no other thread will access object A. Finally thread T1 will also remove object A.

It is guaranteed as well that no thread will iterate over the map.

Does this map need to be synchronized? If yes how would you synchronize it? (ConcurrentHashMap, Collections.synchronizedMap() or synchronized block)

Yes, you would need synchronization, or a concurrent map. Just think about the size of the map: two threads could add an element in parallel, and both increment the size. If you don't synchronize the map, you could have a race condition and it would result in an incorrect size. There are many other things that could go wrong.

But you could also use a different map for each thread, couldn't you?

A ConcurrentHashMap is typically faster that a synchronized HashMap. But the choice depends on your requirements.

If you're sure that there's only one entry per thread and none thread iterates/searches through the map, then why do you need a map?

You can use ThreadLocal object instead which will contain thread-specific data. If you need to keep string-object pairs, you can create an special class for this pair, and keep it inside ThreadLocal field.

class Foo {
   String key;
   Object value;
   ....
}

//below was your Map declaration
//Map<String, Object> map = ...
//Use here ThreadLocal instead
final ThreadLocal<Foo> threadLocalFoo = new ThreadLocal<Foo>();
...
threadLocalFoo.set(new Foo(...));
threadLocalFoo.get() //returns your object
threadLocalFoo.remove() //clears threadLocal container

More info on ThreadLocals you can find in ThreadLocal javadocs .

- First of all its always a practice to write a Thread-safe code , specially in cases like the above, not in all conditions.

- Well its better to use HashTable which is a synchronized Map , or java.util.concurrent.ConcurrentHashMap<K,V> .

You have to synchronize writing operations in the map. If after initializating the map, no thread is going to insert new entries, or delete entries in the map you don't need to synchronize it.

However, in your case (where each thread has its own entry) I'd recommend using ThreadLocal , which allows you to have a "local" object which will have different values per thread.

Hope it helps

I would say that yes. Getting the data is not the issue, adding the data is.

The HashMap has a series of buckets (lists); when you put data to the HashMap , the hashCode is used to decide in which bucket the item goes, and the item is added to the list.

So it can be that two items are added to the same bucket at the same time and, due to some run condition, only one of them is effectively stored.

For this scenario I think ConcurrentHashMap is the best Map, because both Collections.synchronizedMap() or synchronized block (which are basically the same) have more overhead.

If you want to insert entries and not only read them in different threads you have to synchronize them because of the way the HashMap works.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM