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. Thread 1 and Thread 2 tries to put 12th key-value pair.
Thread 1 got execution chance:
- Thread 1 tries to put 12th key-value pair,
- Thread 1 founds that Threshold limit is reached and it creates new Buckets of increased capacity. So map's capacity is increased from 16 to 32.
- Thread 1 now transfers all existing key-value pairs to new buckets.
- Thread 1 points to first key-value pair and next(second) key-value pair to start transfer process.
Thread 1 after pointing to key-value pairs and before starting the transfer process, loose the control and Thread 2 got a chance for execution.
Thread 2 got execution chance:
- Thread 2 tries to put 12th key-value pair,
- Thread 2 founds that Threshold limit is reached and it creates new Buckets of increased capacity. So map's capacity is increased from 16 to 32.
- Thread 2 now transfers all existing key-value pairs to new buckets.
- Thread 2 points to first key-value pair and next(second) key-value pair to start transfer process.
- While transferring key-value pairs from old buckets to new buckets, key-value pairs will be reversed in new buckets because hashmap will add key-value pairs at the start and not at the end. Hashmap adds new key-value pairs at start to avoid traversing linked list every time and keep constant performance.
- Thread 2 will transfer all key-value pairs from old buckets to new buckets and Thread 1 will get chance for execution.
Thread 1 got execution chance:
- Thread 1 before leaving control was pointing to first element and next element of old bucket.
- Now when Thread 1 started putting key-value pairs from old bucket to new bucket. It successfully puts (90, val) and (1, val) in new Bucket.
- When it tries to add next element of (1, val) which is (90, val) into new Bucket, it will end up in infinite loop.
Solution:
To solve this either use a Collections.synchronizedMap
or ConcurrentHashMap
.
ConcurrentHashMap is thread-safe that is the code can be accessed by single thread at a time.
HashMap can be synchronized by using Collections.synchronizedMap(hashMap)
method. By using this method we get a HashMap object which is equivalent to the HashTable object. So every modification is performed on Map is locked on Map object.