Ok, so I am trying to learn multi-threading. I am reading a book and I came across this example for synchronized code blocks:
class CallMe {
void call(String msg) {
System.out.print("[" + msg);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Interrupted");
}
System.out.println("]");
}
}
class Caller implements Runnable {
String msg;
CallMe target;
Thread t;
public Caller(CallMe target, String msg) {
this.target = target;
this.msg = msg;
t = new Thread( this );
t.start();
}
public void run() {
synchronized (target) {
target.call(msg);
}
}
}
public class Scrap {
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");
try {
ob1.t.join();
ob2.t.join();
ob3.t.join();
} catch (Exception e) {
System.out.println("Interrupted");
}
}
}
I got the following output from this:
[Hello]
[World]
[Synchronized]
Then, since I have done some tutorials online, I know that it is good style (or was told this) to create an instance of Object
just for locking. So, I did this and the Caller
class became:
class Caller implements Runnable {
String msg;
CallMe target;
Thread t;
private Object lock = new Object();
public Caller(CallMe target, String msg) {
this.target = target;
this.msg = msg;
t = new Thread( this );
t.start();
}
public void run() {
synchronized (lock) {
target.call(msg);
}
}
}
I was a little surprised when I got this as output:
[Synchronized[Hello[World]
]
]
Of course, this is output where interleaving has taken place and it is not correct. My question is why did this happen? I thought that making the lock Object
would give me the same results. Why did it (or why would it) not give me the same output? I thought that creating the Object
instance was good style and would work the same in this case, and to be honest I can't see why it would be different locking on "target" versus "lock". I guess what I mean to ask is, why does locking on one certain item in this case cause the program to be correct and locking on the other makes it wrong?
Each instance of
Caller
locks on a different instance oflock
. I think you have tosynchronize
on shared instances. Making thelock
into astatic
member would share the same instance across all threads.