Reputation: 9578
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?
Upvotes: 13
Views: 2846
Reputation: 262754
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.
Upvotes: 24