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

发布于 2025-01-15 19:46:43 字数 980 浏览 2 评论 0原文

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

HashMap#resize (java 17) 中,它的作用是

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

如果我有另一个线程开始读取,而 将数据从 oldTab 复制到 newTab 尚未完成,我就注定失败由于 HashMap#gettable 检索值,而由于 table = newTab 现在是一个空数组,因此数据错误?

我不明白的是,为什么不先执行 将数据从 oldTab 复制到 newTab 步骤,然后再将 table 替换为 newTab (表 = newTab):

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

// copy data from oldTab to newTab
...

table = newTab;

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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

×眷恋的温暖 2025-01-22 19:46:43

不,这不是线程安全的。作为 的 javadoc HashMap 指出:

如果多个线程同时访问一个哈希图,并且至少一个
线程的数量在结构上修改了映射,因此必须同步
外部。 (结构修改是任何添加或
删除一个或多个映射;只是改变相关的值
实例已经包含的键不是结构性的
修改。)

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文