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?
How does thread synchronization occurs inside a monitor ? What levels of synchronization can you apply ? The JVM uses locks in conjunction with monitors. A monitor is basically a guardian that watches over a sequence of synchronized code and ensuring that only one thread at a time executes a synchronized piece of code.
A thread can take a lock only once. Synchronized blocks don't offer any mechanism of a waiting queue and after the exit of one thread, any thread can take the lock.
A thread gets blocked if it can't get an access to the synchronized block. The Lock API provides tryLock() method. The thread acquires lock only if it's available and not held by any other thread. This reduces blocking time of thread waiting for the lock.
Locks In Synchronized Methods When a thread invokes a synchronized method, it automatically acquires the intrinsic lock for that method's object and releases it when the method returns. The lock release occurs even if the return was caused by an uncaught exception.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With