Is setting a HashMap thread safe?

后端 未结 4 2081
北荒
北荒 2021-02-20 10:39

I have a HashMap in my program which is accessed by multiple threads, and is occasionally set by a single thread.

For example:

Map

        
相关标签:
4条回答
  • 2021-02-20 10:47

    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:

    • Initializing an object reference from a static initializer.
    • Storing a reference to it into a final field.

    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.

    0 讨论(0)
  • 2021-02-20 10:51

    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.

    0 讨论(0)
  • 2021-02-20 11:01

    HashMap is not thread safe. You can use any of the followings

    1. ConcurrentHashMap.
    2. HashMap with synchronized on the outside.
    3. Different HashMap for each thread.

    Check this similar answer here

    0 讨论(0)
  • 2021-02-20 11:06

    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.

    0 讨论(0)
提交回复
热议问题