Java Hashmap卡在get上

Java Hashmap卡在get上,java,multithreading,hashmap,Java,Multithreading,Hashmap,我对HashMap有一个奇怪的问题。 有多个线程访问同一个hashmap(不是线程安全的) 有时,这个过程会陷入困境 当我检查线程堆栈时,我看到许多线程处于以下状态: java.lang.Thread.State: RUNNABLE at java.util.HashMap.get(HashMap.java:303) 请注意,这种情况非常罕见。而且不能按需复制 为什么会卡住 hashmap上没有同步 键是字符串 有多个线程访问同一个hashmap(不是线程安全的) 听起来您在线程化环

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

有时,这个过程会陷入困境

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

java.lang.Thread.State: RUNNABLE
    at java.util.HashMap.get(HashMap.java:303) 
请注意,这种情况非常罕见。而且不能按需复制

为什么会卡住

hashmap上没有同步

键是字符串

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

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

我建议改为使用
ConcurrentHashMap
,或者用
Collections.synchronizedMap(…)
包装您的
HashMap

更详细地说,这里的问题有两个方面。由于更改内部映射数据时的竞争条件,不能让两个线程更新未同步的映射。锁定是确保互斥和正确数据同步所必需的。一个线程可能会做出其他线程看不到的更改,这可能会覆盖这些更改

另一个问题是内存同步。如果一个线程更新其内存中的
HashMap
,则其他线程不一定会获得相同的映射存储视图。在线程得到部分内存更新之前,这不是问题,其中一些
HashMap
内存已经更新,而其他部分没有更新。例如,您可能会得到一部分bucket数组或一部分bucket存储,当遍历它时会导致线程旋转

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


如果您使用的是预填充的
HashMap
,该HashMap只会被您的线程读取,不会被更新,那么它可能是正常的。我高度依赖于每个线程如何获得对新的
HashMap
的引用。如果构建了
HashMap
,然后通过它们的构造函数(或在它们启动之前)填充并传递到线程中,那么就很好了。但是,如果线程已经在运行,那么这取决于它们如何获得对映射的引用。根据具体情况和您的内存体系结构,他们可能仍然会获得映射内存的部分副本。

您能否详细说明“HashMap内存已损坏”?有这样的例子吗?这是怎么发生的?@user2479100没关系;然而,这很奇怪。正如我在对你的问题的评论中所要求的那样,你能告诉我你的键是什么吗?要回答“为什么不?”请具体参见这里的条目下一个值指向引用原始条目的条目。这发生在重构之后,导致无限循环。我假设你看到了非常高的CPU一旦卡住?我会做一个线程转储的进程。如果其中一个线程卡在
HashMap
方法中,则可以保证这就是问题所在。