Java locks: How equality check for Monitor locks is done in synchronized block?

concurrency, java, locking, synchronized

Solution

No, Java does not use `equals` for lock monitors.

The lock is on the object instance itself. So, in a way, it uses "==", if you will (but in reality, this is not how it is implemented. Every object has a special slot for the current lock owner).

There is no special case for String.

What is happening with Strings, though, is that String literals get pooled, and if you have the same literal more than once, it will result in the same instance (whereas `new X` creates different instances, as would `new String`). If you call `intern` on your "new" Strings, you probably see the same effect.

Problem

When you have couple of `synchronized` blocks on an object (say) `obj` then how does Java check if all these `obj`s are the same or different? For example: ``` public static f() { synchronized ("xyz") { ... } } ``` If the above function `f` is called simultaneously by two threads will they block the other? Notice that each thread will get a new instance of `String` object. To check this I wrote the following test code, and it indeed seems that the above block will work, but then there are other unexpected outcomes. ``` public class Test { public static void main(String[] args){ new Thread() { public void run() { //f1("A", new X()); f1("A", "Str"); } }.start(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //f1("B", new X()); f1("B", "Str"); } public static void f1(String a, Object x) { synchronized(x) { System.out.println("f1: " + a); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("f1: " + a + " DONE"); } } private static class X { public boolean equals(Object o) { System.out.println("equals called"); return true; } public int hashCode() { System.out.println("hashCode called"); return 0; } } } ``` If you run the above code the you will get the following output:- ``` f1: A f1: A DONE f1: B f1: B DONE ``` However, if I comment the `f1("A", "Str");` and `f1("B", "Str");` lines and uncomment the lines above them, then the outcome is:- ``` f1: A f1: B f1: A DONE f1: B DONE ``` Since the `Str` version worked so I was expecting that maybe Java uses `equals` check for `synchronized` block or maybe `hashCode` but from second test it seems, it is not the case at all. Is `String` a special case?

Original source