哈希表卡在get上 [英] Hashmap stuck on get

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

问题描述

我对HashMap有一个奇怪的问题。

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



有时,卡住。



当我检查线程堆栈时,我看到很多状态的线程:

 <$ c $ b $ java.util.HashMap.get(HashMap.java:303)

请注意,这种情况非常罕见。并且无法在需求中转载。



为什么它卡住了?

散列图没有同步。

键是字符串

解决方案


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


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



我建议切换为使用 ConcurrentHashMap ,或者用 Collections.synchronizedMap(...)

包装 HashMap >

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



另一个问题是内存同步。如果一个线程更新其内存中的 HashMap ,其他线程不一定会获得相同的地图存储视图。直到线程获取 partial 内存更新为止,这不是一个问题 - 其中一些 HashMap 内存已被更新,其他部分尚未更新。例如,您可能会获得桶数组的一部分或桶存储的一部分,这些数据在遍历时会导致线程旋转。

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



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


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

Sometime, the process gets stuck.

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.

Why it gets stuck?

There is no synchronization on hashmap.

keys are strings

解决方案

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

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.

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.

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.

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.

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

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