HashMap resize() 同时单线程写多线程读

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

首先,我假设如果始终只有一个编写器线程,那么我应该可以安全地使用 HashMap 而不是 ConcurrentHashMap

HashMap#resize(java17)中,它所做的是

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
...

如果我有另一个线程开始读取而 copy data from oldTab to newTab 未完成,我注定会收到错误数据,因为 HashMap#gettable 检索值,现在是空的数组因为 table = newTab?

我不明白的是为什么不先执行 copy data from oldTab to newTab 步骤,然后再将 table 替换为 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;

不,这不是线程安全的。正如 HashMap 的 javadoc 所述:

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.)

一个线程正在更改地图而其他线程正在并发读取这一事实根据定义是不安全的。您将需要使用 ConcurrentHashMapCollections.synchronizedMap 或其他同步解决方案。