Hashmap坚持得到

时间:2013-06-12 16:03:08

标签: java multithreading hashmap

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

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

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

java.lang.Thread.State: RUNNABLE
    at java.util.HashMap.get(HashMap.java:303) 

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

为什么会卡住?

hashmap上没有同步。

键是字符串

1 个答案:

答案 0 :(得分:20)

  

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

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

我建议改为使用ConcurrentHashMap或用HashMap包裹Collections.synchronizedMap(...)

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

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

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

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