简体   繁体   中英

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

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?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM