Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do I have to use a thread-safe Map implementation when only reading from it?

If I do the following.

  • Create a HashMap (in a final field)
  • Populate HashMap
  • Wrap HashMap with unmodifiable wrapper Map
  • Start other threads which will access but not modify the Map

As I understand it the Map has been "safely published" because the other threads were started after the Map was fully populated so I think it is ok to access the Map from multiple threads as it cannot be modified after this point.

Is this right?

like image 367
Mike Q Avatar asked May 10 '11 13:05

Mike Q


4 Answers

This is perfectly fine concerning the map itself. But you need to realize the making the map unmodifiable will only make the map itself unmodifiable and not its keys and values. So if you have for example a Map<String, SomeMutableObject> such as Map<String, List<String>>, then threads will still be able to alter the value by for example map.get("foo").add("bar");. To avoid this, you'd like to make the keys/values immutable/unmodifiable as well.

like image 185
BalusC Avatar answered Oct 16 '22 19:10

BalusC


As I understand it the Map has been "safely published" because the other threads were started after the Map was fully populated so I think it is ok to access the Map from multiple threads as it cannot be modified after this point.

Yes. Just make sure that the other threads are started in a synchronized manner, i.e. make sure you have a happens-before relation between publishing the map, and starting the threads.

This is discussed in this blog post:

[...] This is how Collections.unmodifiableMap() works.

[...]

Because of the special meaning of the keyword "final", instances of this class can be shared with multiple threads without using any additional synchronization; when another thread calls get() on the instance, it is guaranteed to get the object you put into the map, without doing any additional synchronization. You should probably use something that is thread-safe to perform the handoff between threads (like LinkedBlockingQueue or something), but if you forget to do this, then you still have the guarantee.

like image 27
aioobe Avatar answered Oct 16 '22 21:10

aioobe


You are correct. There is no need to ensure exclusive access to the data structure by different threads by using mutex'es or otherwise since it's immutable. This usually greatly increases performance.

Also note that if you only wrap the original Map rather than creating a copy, ie the unmodifiable Map delegates method calls further to the inner HashMap, modifying the underlying Map may introduce race condition problems.

like image 1
vidstige Avatar answered Oct 16 '22 19:10

vidstige


Immutable map is born to thread-safe. You could use ImmutableMap of Guava.

like image 1
卢声远 Shengyuan Lu Avatar answered Oct 16 '22 20:10

卢声远 Shengyuan Lu