You very likely have a deadlock.
If you want to avoid deadlocks, every thread must always acquire locks in the same order. When you use String.intern() to get your locks, you are locking on an instance that any code in the entire JVM has access to, and lock on. Most likely, other threads in your own code are deadlocking, but it doesn't have to be.
I'm not sure what you mean in your answer by "key.intern() guarantee uniqueness". The intern()
method reduces uniqueness by returning the same object for every string that's equivalent.
String s1 = new String(new char[] { 'c', 'o', 'm', 'm', 'o', 'n' }).intern();
String s2 = new String("commo" + (s1.charAt(s1.length() - 1)).intern();
String s3 = "common";
if ((s1 == s2) && (s1 == s3))
System.out.println("There's only one object here.");
The code above will demonstrate that even though you created two unique instances, by interning them, you replaced them with a single, canonical instance.
There's danger any time you use an object that's visible outside your own code as a lock. Try to stick to private members, objects that you don't allow to escape from your own stack, etc.