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;
CodePudding user response:
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.