Hashmap 卡在 get 上 [英] Hashmap stuck on get

查看:30
本文介绍了Hashmap 卡在 get 上的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a strange issue with HashMap.
There are multiple threads that accessing same hashmap (not threadsafe).

有时,该过程会卡住.

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

when I inspect the thread stack, i see many threads in state:

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

请注意,这种情况非常罕见.并且不能按需复制.

Note this happens very rare. And can't be reproduced on demand.

为什么会卡住?

hashmap 上没有同步.

There is no synchronization on hashmap.

键是字符串

推荐答案

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

There are multiple threads that accessing same hashmap (not threadsafe).

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

Sounds like you are using this HashMap in a threaded environment without proper synchronization. You are hitting a problem where the HashMap memory is corrupted and a thread is most likely spinning because of this. You cannot update an unsynchronized map and read from it using multiple threads. In some situations you can build a read-only map and then share it without synchronization in multiple threads.

我建议改用 ConcurrentHashMap 或用 Collections.synchronizedMap(...) 包装您的 HashMap.

I would suggest switching to use ConcurrentHashMap instead or wrap your HashMap with Collections.synchronizedMap(...).

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

To elaborate more, the issue here is two fold. You cannot have two threads updating an unsynchronized map because of race conditions when altering internal map data. Locking is necessary to ensure mutex and proper data synchronization. One thread might make changes not seen by the other thread which could overwrite them.

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

The other issue is memory synchronization. If one thread updates the HashMap in its memory, other threads won't necessarily get the same view of the map's storage. This isn't a problem until a thread gets partial memory update -- where some of the HashMap memory has been updated and other portions have not. You might, for example, get a portion of the bucket array or a portion of the bucket storage which when traversed causes the thread to spin.

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

One of the main reasons multi-processor boxes run threaded code faster is that the threads can use per-processor cached memory. The cached memory is the problem. One processor could be reading or changing its cached memory at the same time another processor is doing the same. Synchronizing local cached memory with central storage is one of things you need to worry about and the reasons why synchronization is so important.

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

If you are using a pre-populated HashMap that is only going to be read by your threads and never updated then it may be ok. I depends highly on how each of the threads got the reference to the new HashMap. If the HashMap was constructed and then populated and passed into the threads via their constructor (or before they were started) then you are good. However if the threads are already running then it depends on how they get a reference to the map. They may still get a partial copy of the map's memory depending on the circumstances and your memory architecture.

这篇关于Hashmap 卡在 get 上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆