Hashmap坚持得到

use*_*100 5 java multithreading hashmap

我对HashMap有一个奇怪的问题.
有多个线程访问相同的hashmap(不是线程安全).

有时候,这个过程会被卡住.

当我检查线程堆栈时,我看到许多线程处于状态:

java.lang.Thread.State: RUNNABLE
    at java.util.HashMap.get(HashMap.java:303) 
Run Code Online (Sandbox Code Playgroud)

注意这种情况非常罕见.并且无法按需复制.

为什么会卡住?

hashmap上没有同步.

键是字符串

Gra*_*ray 21

有多个线程访问相同的hashmap(不是线程安全).

听起来好像是HashMap没有正确同步的线程环境中使用它.您遇到的问题是HashMap内存已损坏且线程最有可能因此而旋转.您无法更新未同步的映射并使用多个线程从中读取.在某些情况下,您可以构建只读映射,然后在多个线程中无需同步即可共享它.

我建议切换到使用ConcurrentHashMap替代或包装你HashMapCollections.synchronizedMap(...).

要详细说明,这里的问题有两个方面.由于更改内部地图数据时的竞争条件,您不能让两个线程更新未同步的地图.锁定是确保互斥和正确数据同步所必需的.一个线程可能会使另一个线程看不到可能覆盖它们的更改.

另一个问题是内存同步.如果一个线程HashMap在其内存中更新,则其他线程不一定会获得地图存储的相同视图.在线程获得部分内存更新之前,这不是问题- 其中一些HashMap内存已更新而其他部分尚未更新.例如,您可能获取桶阵列的一部分或桶存储的一部分,当遍历时导致线程旋转.

多处理器盒运行线程代码的主要原因之一是线程可以使用每处理器缓存的内存.缓存的内存是问题所在.一个处理器可以在另一个处理器执行相同操作的同时读取或更改其缓存的内存.将本地缓存内存与中央存储同步是您需要担心的事情之一,以及同步如此重要的原因.

如果您使用的是预先填充的HashMap,只会被您的线程读取并且从未更新过,那么它可能没问题.我非常依赖每个线程如何获得对新的引用HashMap.如果HashMap构造然后填充并通过它们的构造函数(或者在它们启动之前)传递到线程中,那么你就是好的.但是,如果线程已经运行,那么它取决于它们如何获得对地图的引用.根据具体情况和内存架构,他们仍然可以获得地图内存的部分副本.

  • 回答"为什么不呢?" 具体请参见http://mailinator.blogspot.com/2009/06/beautiful-race-condition.html (4认同)
  • 基本上,条目下一个值指向引用原始条目的条目.这在重组后发生,导致无限循环.我假设你一旦卡住就看到了很高的CPU? (3认同)