m0s
m0s

Reputation: 4280

Do I need to worry about thread safety if I am only reading from a collection?

I want to pass a pre-built Map to multiple threads that are going to only read the values from the Map simultaneously. Do I need to worry about concurrent access and use the ConcurrentHashMap instead of HashMap in this case?

Upvotes: 5

Views: 733

Answers (7)

Stephen C
Stephen C

Reputation: 719596

You still need to make sure that there is a "happens-before" relationship between the thread that creates and initializes the Map, and the threads that subsequently read it. If there is no such relationship, it is theoretically possible for the reading threads to see stale data.

If you create and populate the Map in the thread that starts the other threads ... before it does this ... you should be fine.

Another simple way to ensure safety is to do something like this:

public class Foo {
    private final Map map;

    public Foo(....) {
        map = new HashMap();
        // populate
    }

    public Map getMap() {
        // If the 'map' is final, and nothing changes it apart from 
        // the constructor, this method doesn't need to be synchronized.
    }

Both of these will result in a "happens-before" relationship between the creation / initialization, and each thread's first use of the Map.

You could also declare map in the above to be volatile, but is likely to cause more cache flushes than strictly need to occur; i.e. you'll take a small performance hit.

Upvotes: 7

Marko Topolnik
Marko Topolnik

Reputation: 200296

You always need to worry about thread safety. In your specific example, it will be enough if you

  1. fully construct the map in a single thread;
  2. publish it to other threads by setting a volatile variable to refer to it.

Or, if that is an option, make sure the threads are not started until the map is ready.

Upvotes: 3

Francisco Spaeth
Francisco Spaeth

Reputation: 23913

What you could do, additionally, in order to ensure that will be handled just for reading operations is to give back an Collections.unmodifiableMap(Map).

Upvotes: 3

akaHuman
akaHuman

Reputation: 1352

No you dont need to use it. Conflicts are generated only in following cases:

  • When some threads may read the data, while others may try to overwrite it.
  • The second is when every thread tries to update the data.

When each thread is only trying to read the values, no conflicts are generated.

Upvotes: 1

ams
ams

Reputation: 62772

It is safe to pass the HashMap if all the threads are reading it. However, before passing the map I would call Collections.unmodifiableMap() to make sure that if one of thread accidentally modified it because some programmer in the future did not respect the current contract you will get an exception.

Upvotes: 2

Ajinkya
Ajinkya

Reputation: 22720

No, You dont have to worry about it.
Unless until someone going to change pre-built map while thread are accessing it.

Upvotes: 1

Matzi
Matzi

Reputation: 13925

In theory, concurrent reading should not cause problems on collections.

However if you modify it even once, it is prone to error, and then you should use a concurrent version.

Upvotes: 2

Related Questions