Search code examples
javaconcurrencyhashmap

HashMap resize() while single thread writing and multiple threads reading


First of all, am I correct to assume that if there's always going to be a single writer thread, then I should be safe to use HashMap but not ConcurrentHashMap?

In HashMap#resize (java 17), what it does is

Node<K,V>[] oldTab = table; //table is the underlying storage transient Node<K,V>[] table
...
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];

table = newTab;

// copy data from oldTab to newTab
...

If I have another thread starts reading while copy data from oldTab to newTab is not finished, I'll be doomed with wrong data since HashMap#get retrieves value from table, which is now an empty array because of table = newTab?

What I don't understand is why not do the copy data from oldTab to newTab step first, before replacing table with newTab (table = newTab):

Node<K,V>[] oldTab = table;
...
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];

// copy data from oldTab to newTab
...

table = newTab;


Solution

  • No, this is not thread safe. As the javadoc of HashMap states:

    If multiple threads access a hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more mappings; merely changing the value associated with a key that an instance already contains is not a structural modification.)

    The fact that one thread is changing the map while others are reading concurrently is by definition unsafe. You will need to use ConcurrentHashMap or Collections.synchronizedMap or another synchronization solution.