This question already has an answer here:
I am just having hard time to understand concept behind putting wait()
in Object
class. For this questions sake consider if wait()
and notifyAll()
are in Thread
class.
class Reader extends Thread {
Calculator c;
public Reader(Calculator calc) {
c = calc;
}
public void run() {
synchronized(c) { //line 9
try {
System.out.println("Waiting for calculation...");
c.wait();
} catch (InterruptedException e) {}
System.out.println("Total is: " + c.total);
}
}
public static void main(String [] args) {
Calculator calculator = new Calculator();
new Reader(calculator).start();
new Reader(calculator).start();
new Reader(calculator).start();
calculator.start();
}
}
class Calculator extends Thread {
int total;
public void run() {
synchronized(this) { //Line 31
for(int i=0;i<100;i++) {
total += i;
}
notifyAll();
}
}
}
My Question is that what difference it could have made? In line 9 we are acquiring lock on object c and then performing wait which satisfy the condition for wait that we need to acquire lock on the object before we use wait and so is case for notifyAll we have acquired lock on object of Calculator at line 31.
In simple terms, the reasons are as follows.
Object
has monitors.Object
. Only one thread can hold object monitor at a time forsynchronized
methods/blocks.wait(), notify() and notifyAll()
method being inObject
class allows all the threads created on thatobject
to communicate with othersynchronized or Lock
API) and Communication (wait() and notify()
) are two different concepts.If
Thread
class containswait(), notify() and notifyAll()
methods, then it will create below problems:Thread
communication problemSynchronization
on object won’t be possible. If each thread will have monitor, we won’t have any way of achieving synchronizationInconsistency
in state of objectRefer to this article for more details.
This is just my 2 cents on this question...not sure if this holds true in its entirety.
Each Object has a monitor and waitset --> set of threads (this is probably more at OS level). This means the monitor and the waitset can be seen as private members of an object. Having wait() and notify() methods in Thread class would mean giving public access to the waitset or using get-set methods to modify the waitset. You wouldnt want to do that because thats bad designing.
Now given that the Object knows the thread/s waiting for its monitor, it should be the job of the Object to go and awaken those threads waiting for it rather than an Object of thread class going and awakening each one of them (which would be possible only if the thread class object is given access to the waitset). However, it is not the job of a particular thread to go and awaken each of the waiting threads. (This is exactly what would happened if all these methods were inside the Thread class). Its job is just to release the lock and move ahead with its own task. A thread works independently and does not need to know whihc other threads are waiting for the objects monitor (it is an unnecessary detail for the thread class object). If it started awakening each thread on its own.. it is moving from away its core functionality and that is to carry out its own task. When you think about a scene where there might 1000's of threads.. you can assume how much of a performance impact it can create. Hence, given that Object Class knows who is waiting on it, it can carry out the job awakening the waiting threads and the thread which sent notify() can carry out with its further processing.
To give an analogy (perhaps not the right one but cant think of anything else). When we have a power outage, we call a customer representative of that company because she knows the right people to contact to fix it. You as a consumer are not allowed to know who are the engineers behind it and even if you know, you cannot possibly call each one of them and tell them of your troubles (that is not ur duty. Your duty is to inform them about the outage and the CR's job is to go and notify(awaken) the right engineers for it).
Let me know if this sounds right... (I do have the ability to confuse sometimes with my words).
wait and notify operations work on implicit lock, and implicit lock is something that make inter thread communication possible. And all objects have got their own copy of implicit object. so keeping wait and notify where implicit lock lives is a good decision.
Alternatively wait and notify could have lived in Thread class as well. than instead of wait() we may have to call Thread.getCurrentThread().wait(), same with notify. For wait and notify operations there are two required parameters, one is thread who will be waiting or notifying other is implicit lock of the object . both are these could be available in Object as well as thread class as well. wait() method in Thread class would have done the same as it is doing in Object class, transition current thread to waiting state wait on the lock it had last acquired.
So yes i think wait and notify could have been there in Thread class as well but its more like a design decision to keep it in object class.
wait - wait method tells the current thread to give up monitor and go to sleep.
notify - Wakes up a single thread that is waiting on this object's monitor.
So you see wait() and notify() methods work at the monitor level, thread which is currently holding the monitor is asked to give up that monitor through wait() method and through notify method (or notifyAll) threads which are waiting on the object's monitor are notified that threads can wake up.
Important point to note here is that monitor is assigned to an object not to a particular thread. That's one reason why these methods are in Object class. To reiterate threads wait on an Object's monitor (lock) and notify() is also called on an object to wake up a thread waiting on the Object's monitor.
Answer to your first question is As every object in java has only one
lock(monitor)
andwait(),notify(),notifyAll()
are used for monitor sharing thats why they are part ofObject
class rather thanThread
class.