Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hashmap stuck on get

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

like image 469
user2479100 Avatar asked Jun 12 '13 16:06

user2479100


People also ask

What's wrong using HashMap in multithreaded environment when get () method go to infinite loop?

What's wrong using HashMap in multithreaded environment? When get() method go to infinite loop? It is a bug to have multiple threads use a non-synchronized collection (really any mutable class) in an unprotected manner. Certain if each thread had their own HashMap instance then this is not an issue.

When GET method go to infinite loop in HashMap?

Situation: The default capacity of HashMap is 16 and Load factor is 0.75, which means HashMap will double its capacity when 12th Key-Value pair enters in the map (16 * 0.75 = 12). When 2 thread tries to access HashMap simultaneously, then you may encounter infinite loop.

What is wrong with HashMap in multithreaded environment?

The HashMap is non-thread-safe and can not be used in a Concurrent multi-threaded environment. Comparatively, ConcurrentHashMap is a thread-safe and specially designed for use in multi-threaded and Concurrent environment.


1 Answers

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.

like image 136
Gray Avatar answered Oct 12 '22 04:10

Gray