I have a HashMap
in my program which is accessed by multiple threads, and is occasionally set by a single thread.
For example:
Map
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.
HashMap is not thread safe. You can use any of the followings
Check this similar answer here
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. For example, the following would be fine:
// this refresh code would be thread-safe
Map<String, String> copy = new HashMap<String, String>(myMap);
copy.put(x, y); // change the map
myMap = copy;
// you might also consider
myMap = Collections.unmodifiableMap(copy);
// to make sure that the non-thread-safe map will never be mutated
One thing to consider with this pattern is that you may want the myMap field to be declared as volatile so that all threads will get the most recent version of myMap whenever they read from that variable.
Finally, as other posters have mentioned ConcurrentHashMap may be a better approach depending on the complexity of the refresh code. One disadvantage of ConcurrentHashMap is that it doesn't offer any way to batch the operations, so you'd have to make sure that the state at every point during the refresh process was valid for the rest of your application to consume.