在doc中,它说
似乎表明更改与实例已包含的键关联的值不需要外部同步。但是我认为这不是线程安全的。正确的?
最佳答案
出于线程可见性的目的,是的,如果您有两个使用映射进行通信的线程,则需要进行外部同步。但是不同步的结构更改可能会完全破坏映射(想象一下,当2个线程放置一个新映射并且两个线程都开始重新哈希映射时),而更改映射的值将不会产生太大的影响。
即使只有一个线程进行结构修改,如果增加/重新排列后备阵列也是有问题的。使用相同数组(或旧数组,如果增长了数组,则使用其他数组)的其他线程可能会遇到丢失的更新(线程将值放在旧数组而不是新数组中),映射消失(线程将值放在数组中,而另一个线程是)。重新哈希同一数组,将值放入错误的存储区中),依此类推。
那么什么时候可以安全不同步呢?几乎从不。一种安全的情况是使用线程仅访问“其”条目的预构建 map ,例如
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/