I have a HashMap
in my program which is accessed by multiple threads, and is occasionally set by a single thread.
For example:
Map<String, String> myMap = new HashMap<String, String>();
This is accessed by multiple threads. Once an hour, a single thread calls:
myMap = myRefreshedVersionOfTheMap;
So my question is whether or not this is thread safe. If both maps always have the key "importantKey"
, is it possible for a reading thread to ever access the map at a time when "importantKey"
does not exist?
Edit:
Thanks to the answers, I've realized this question is actually independent of the HashMap
. It was more a question about object reference assignment.
First off, Java's HashMap class is not thread safe, so there are no guarantees when reads and writes are happening concurrently. However, since reads and writes to references in Java are atomic, then the pattern you described could be thread-safe as long as the refresh code is not mutating the old map.
Unlike the new collection implementations, Hashtable is synchronized. If a thread-safe implementation is not needed, it is recommended to use HashMap in place of Hashtable, says the javadoc about Hashtable. Same, if you need a thread-safe ArrayList one day, use Vector.
For example when we create a map as a local variable of a method, we are assured that the map instance is accessed in a thread safe way as each thread has its own execution stack during a method invocation. When the map is a field of the class, synchronization may be needed or at least we could wonder if it is.
A HashMapthat is updated without synchronization will break evenif the threads are using disjoint sets of keys. Here are just some1of the things that can go wrong. If one thread does a put, then another thread may see a stale value for the hashmap's size.
This is not thread safe. Even though there are no writes to the map itself after the point of publication (from the point of view of the thread doing the publication), and reference assignment is atomic, the new Map<>
has not been safely published. It particular, there are writes to the Map during its construction - either in the constructor, or after, depending on how you add those elements, and those writes may or may not be seen by other threads, since even though they intuitively occur before the map is published to the other threads, this isn't formally the case according to the memory model.
For an object to be safely published, it must be communicated to the outside world using some mechanism that either establishes a happens-before relationship between the object construction, the reference publication and the reference read, or it must use a handful of narrower methods which are guaranteed to be safe for publishing:
Your idiom would be safe if you declared myMap volatile
. More details on safe publication can be found in JCIP (highly recommended), or here, or in this longer answer on a similar topic.
If you mean you are creating an entirely new Map
and are assigning it to myMap
which is what the other threads are accessing, then yes. Reference assignment is atomic. It's threadsafe because you are not modifying the contents of a Map
while other threads are reading from it - you just have multiple threads reading from a Map
.
You just need to declare it volatile
so other threads don't cache it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With