I have this example code based on a sample I found on the web to illustrate how to use wait()
and notify()
. Let me preface the code sample with the following statement a Java textbook makes about wait
and notify
.
A thread can't invoke a wait or notify method on an object unless it owns that's object's lock
Now take a look at this code and the output:
public class ThreadTester
{
public class Message {
private String msg;
public Message(String str){ this.msg=str;}
public String getMsg() { return msg; }
public void setMsg(String str) { this.msg=str;}
}
public class Waiter implements Runnable{
private Message msg;
public Waiter(Message m){
this.msg = m;
}
public void run() {
String name = Thread.currentThread().getName();
synchronized (msg) {
try{
System.out.println(name + " acquired lock to msg object. waiting to get notified");
msg.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(name + " waiter done at time: " + System.currentTimeMillis());
}
System.out.println(name + " waiter giving up msg object lock");
}
}
public class Notifier implements Runnable {
private Message msg;
public Notifier(Message msg) {
this.msg = msg;
}
public void run() {
String name = Thread.currentThread().getName();
System.out.println(name + " started");
try {
Thread.sleep(5000);
synchronized (msg) {
String localMesg = name + " acquired lock to msg object. Notifier work done.";
System.out.println(localMesg);
msg.setMsg(localMesg);
msg.notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
void runtest() {
Message msg = new Message("process it");
Waiter waiter1 = new Waiter(msg);
new Thread(waiter1,"waiter1").start();
Waiter waiter2 = new Waiter(msg);
new Thread(waiter2, "waiter2").start();
Notifier notifier = new Notifier(msg);
new Thread(notifier, "notifier").start();
System.out.println("All the threads are started");
}
public static void main(String [] args) {
new ThreadTester().runtest();
}
}
Here is the output:
waiter1 acquired lock to msg object. waiting to get notified
waiter2 acquired lock to msg object. waiting to get notified
All the threads are started
notifier started
notifier acquired lock to msg object. Notifier work done.
waiter1 waiter done at time: 1419745413721
waiter1 waiter giving up msg object lock
Now the question is, how can waiter2
or notifier
threads acquire the msg object's lock when waiter1
thread is still holding it? That seems to directly contradict the Java textbook statement I cite above. What am I missing?
Thanks for any help.