Joker
Joker

Reputation: 11154

DeadLock In ConcurrentHashMap

Following code when run, never terminates and stuck in endless loop.

I am not sure where it is getting stuck.

Interesting thing is when I change AaAa to AAAA every thing works fine as expected.

 public class Test {

    public static void main(String[] args) {

        Map<String, Integer> map = new ConcurrentHashMap<>(16);
        map.computeIfAbsent(
                "AaAa",
                key -> {
                    return map.computeIfAbsent(
                            "BBBB",
                            key2 -> 42);
                }
        );
    }

}

Can some one help me understanding this behavior.

Upvotes: 3

Views: 1890

Answers (2)

Mehraj Malik
Mehraj Malik

Reputation: 15874

Whenever two different objects have the same hash code, we call this a collision.

A collision is nothing critical, it just means that there is more than one object in a single bucket, so a HashMap lookup has to look again to find the right object. A lot of collisions will degrade the performance of a system, but they won’t lead to incorrect results.

But if you mistake the hash code for a unique handle to an object, e.g use it as a key in a Map, then you will sometimes get the wrong object.

In Java there are 4,294,967,296 compartments (2^32 possible int values). With 4 billion slots, collisions seem to be extremely unlikely, right? Because even though collisions are rare, they are inevitable. For example, the Strings "Aa" and "BB" produce the same hashCode: 2112."AaAa" and "BBBB" have the same hashCode() - 2031744 and many more.

Objects that are equal must have the same hash code within a running process

Please note that this does not imply the following common misconceptions:

  • Unequal objects must have different hash codes – WRONG!
  • Objects with the same hash code must be equal – WRONG!

Upvotes: 0

Eran
Eran

Reputation: 393936

"AaAa" and "BBBB" have the same hashCode() - 2031744. Therefore both keys are mapped to the same bin of the Map.

The outer map.computeIfAbsent locks that bin, and the inner map.computeIfAbsent tries to lock it before the lock is released - hence the deadlock.

Upvotes: 16

Related Questions