java - 理解 HashMap 中的 `structural modification`

标签 java multithreading hashmap

doc , 它说

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

这似乎表明更改与实例已包含的键关联的值不需要外部同步。但我认为这不是线程安全的。对吧?

最佳答案

是的,出于线程可见性的目的,如果您有两个使用 map 进行通信的线程,则需要外部同步。但是不同步的结构更改有可能完全破坏映射(想象一下,当 2 个线程放置一个新映射并且都开始重新散列映射时),而更改映射值不会产生那么显着的影响。

即使只有一个线程进行结构修改,如果后备数组增长/重新散列也会出现问题。使用相同数组(或旧数组,如果数组增长)的其他线程可能会遇到丢失更新(线程将值放入旧数组而不是新数组)、消失的映射(线程将值放入数组,而另一个线程是重新散列相同的数组,值被放入错误的桶中)等等。

那么什么时候同步是安全的?几乎从不。一个安全的情况是一个预构建的映射,线程只访问“他们的”条目,比如

thread1: map.get("A");
thread2: map.put("B", "1");   // Assume "B" was in the map already
thread3: map.get("C");

没有问题,因为没有结构变化并且线程不共享 key 。一旦开始在线程之间共享 key ,就会出现竞争条件和可见性问题。如果您引入结构更改,这些可见性问题可能会导致 map 中的数据丢失。

关于java - 理解 HashMap 中的 `structural modification`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57867464/

相关文章:

java - 如何获取传递的集合<通用类型>的子集合,其中成员扩展或实现另一个集合?

java - 使用 Jackson 解析器将 JSON 数组转换为 HashMap<String,Object>

java - 删除重复元素并计算 ArrayList 中的重复次数

java - Log4j 记录器和并发

java - 从数组中删除维度

.net - 如何在线程中打开表单并强制其保持打开状态

c++ - 尝试等待 boost::condition_Variable 时出现 "unique_lock has no mutex: Operation not permitted"错误

c# - HttpWebRequest 的并发限制

Java嵌套ConcurrentHashMap是线程安全的吗?

Java string.matches() 返回错误语句