We know that HashMap
is a non-synchronized collection whereas its synchronized counter-part is HashTable
. So, when you are accessing the collection in a multithreaded environment and all threads are accessing a single instance of collection, then it's safer to use HashTable
for various obvious reasons e.g. to avoid dirty reads and to maintain data consistency. In the worst case, this multithreaded environment can result in an infinite loop as well.
Yes, it is true. HashMap.get()
can cause an infinite loop. Let us see how??
If you look at the source code HashMap.get(Object key)
method, it looks like this:
public Object get(Object key) {
Object k = maskNull(key);
int hash = hash(k);
int i = indexFor(hash, table.length);
Entry e = table[i];
while (true) {
if (e == null)
return e;
if (e.hash == hash && eq(k, e.key))
return e.value;
e = e.next;
}
}
while(true){...}
can always be a victim of an infinite loop at runtime in a
multithreaded environment, IF, somehow e.next can point to itself. This will result in an infinite loop. But, how e.next will point to itself?
This can happen in void transfer(Entry[] newTable)
method, which is invoked at the time the HashMap resizing is done.
do {
Entry next = e.next;
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e
= next;
} while (e != null);
This piece of code is prone to produce the above condition if resizing happens and at the same time, other threads tried to modify the map instance.
The only way to avoid this scenario is to use synchronization in code, or better, use the synchronized collection.