Reputation: 105
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
Upvotes: 5
Views: 6066
Reputation: 116878
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.
Upvotes: 22