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#get
从 table
检索值,现在是空的数组因为 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.)
一个线程正在更改地图而其他线程正在并发读取这一事实根据定义是不安全的。您将需要使用 ConcurrentHashMap
或 Collections.synchronizedMap
或其他同步解决方案。
首先,我假设如果始终只有一个编写器线程,那么我应该可以安全地使用 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#get
从 table
检索值,现在是空的数组因为 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.)
一个线程正在更改地图而其他线程正在并发读取这一事实根据定义是不安全的。您将需要使用 ConcurrentHashMap
或 Collections.synchronizedMap
或其他同步解决方案。