I'm learning to write better multi-threaded programs, thread-safe and deterministic. I came across this piece of code
// File Name : Callme.java
// This program uses a synchronized block.
class Callme {
void call(String msg) {
System.out.print("[" + msg);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Interrupted");
}
System.out.println("]");
}
}
// File Name : Caller.java
class Caller implements Runnable {
String msg;
Callme target;
Thread t;
public Caller(Callme targ, String s) {
target = targ;
msg = s;
t = new Thread(this);
t.start();
}
// synchronize calls to call()
public void run() {
synchronized(target) { // synchronized block
target.call(msg);
}
}
}
// File Name : Synch.java
public class Synch {
public static void main(String args[]) {
Callme target = new Callme();
Caller ob1 = new Caller(target, "Hello");
Caller ob2 = new Caller(target, "Synchronized");
Caller ob3 = new Caller(target, "World");
// wait for threads to end
try {
ob1.t.join();
ob2.t.join();
ob3.t.join();
} catch(InterruptedException e) {
System.out.println("Interrupted");
}
}
}
which produces the following output(tried it ~100 times)
[Hello]
[World]
[Synchronized]
So my first question is, is this output guaranteed? I also observed that if I change sleep to 100
it still produces the same output, but if I change sleep to 10
the output changes to
[Hello]
[Synchronized]
[World]
Second question is, If it's guaranteed, why? Last but not the least, Why this output? I expected it to be
[Hello]
[Synchronized]
[World]
I think there are two pretty interesting things going on here.
The code tries to rely on a synchronization block to keep the order of the calls consistent. There are two problems with this:
1) The synchronization block isn't fair (see Synchronization vs Lock), so which ever thread gets to the locked synchronized block first may not be the first to be granted access to the object. According to that post, however, synchronization at the method level public synchronized void run() would be a fair lock (in Java 1.5, not Java 1.6), so the first one waiting on the lock would be the first granted access to the object.
2) Even if the synchronization block was fair, the first thread may not, in theory, (the [synchronized]) may not be the first to call some of the code in run(). The [world] could actually call it first.
No, the output is not guaranteed.
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