Why Are Wait() and Notify() Declared in Java's Object Class

Why are wait() and notify() declared in Java's Object class?

Because, you wait on a given Object (or specifically, its monitor) to use this functionality.

I think you may be mistaken on how these methods work. They're not simply at a Thread-granularity level, i.e. it is not a case of just calling wait() and being woken up by the next call to notify(). Rather, you always call wait() on a specific object, and will only be woken by calls to notify on that object.

This is good because otherwise concurrency primitives just wouldn't scale; it would be equivalent to having global namespaces, since any calls to notify() anywhere in your program would have the potential to mess up any concurrent code as they would wake up any threads blocking on a wait() call. Hence the reason that you call them on a specific object; it gives a context for the wait-notify pair to operate on, so when you call myBlockingObject.notify(), on a private object, you can be sure that you'll only wake up threads that called wait methods in your class. Some Spring thread that might be waiting on another object will not be woken up by this call, and vice versa.

Edit: Or to address it from another perspective - I expect from your question you thought you would get a handle to the waiting thread and call notify() on that Thread to wake it up. The reason it's not done this way, is that you would have to do a lot of housekeeping yourself. The thread going to wait would have to publish a reference to itself somewhere that other threads could see it; this would have to be properly synchronized to enforce consistency and visibility. And when you want to wake up a thread you'd have to get hold of this reference, awaken it, and remove it from wherever you read it from. There's a lot more manual scaffolding involved, and a lot more chance of going wrong with it (especially in a concurrent environment) compared to just calling myObj.wait() in the sleeping thread and then myObj.notify() in the waker thread.

Concept behind putting wait(),notify() methods in Object class

I am just having hard time to understand concept behind putting wait() in object class For this questions sake consider as if wait() and notifyAll() are in thread class

In the Java language, you wait() on a particular instance of an Object – a monitor assigned to that object to be precise. If you want to send a signal to one thread that is waiting on that specific object instance then you call notify() on that object. If you want to send a signal to all threads that are waiting on that object instance, you use notifyAll() on that object.

If wait() and notify() were on the Thread instead then each thread would have to know the status of every other thread. How would thread1 know that thread2 was waiting for access to a particular resource? If thread1 needed to call thread2.notify() it would have to somehow find out that thread2 was waiting. There would need to be some mechanism for threads to register the resources or actions that they need so others could signal them when stuff was ready or available.

In Java, the object itself is the entity that is shared between threads which allows them to communicate with each other. The threads have no specific knowledge of each other and they can run asynchronously. They run and they lock, wait, and notify on the object that they want to get access to. They have no knowledge of other threads and don't need to know their status. They don't need to know that it is thread2 which is waiting for the resource – they just notify on the resource and whomever it is that is waiting (if anyone) will be notified.

In Java, we then use objects as synchronization, mutex, and communication points between threads. We synchronize on an object to get mutex access to an important code block and to synchronize memory. We wait on an object if we are waiting for some condition to change – some resource to become available. We notify on an object if we want to awaken sleeping threads.

// locks should be final objects so the object instance we are synchronizing on,
// never changes
private final Object lock = new Object();
...
// ensure that the thread has a mutex lock on some key code
synchronized (lock) {
...
// i need to wait for other threads to finish with some resource
// this releases the lock and waits on the associated monitor
lock.wait();
...
// i need to signal another thread that some state has changed and they can
// awake and continue to run
lock.notify();
}

There can be any number of lock objects in your program – each locking a particular resource or code segment. You might have 100 lock objects and only 4 threads. As the threads run the various parts of the program, they get exclusive access to one of the lock objects. Again, they don't have to know the running status of the other threads.

This allows you to scale up or down the number of threads running in your software as much as you want. You find that the 4 threads is blocking too much on outside resources, then you can increase the number. Pushing your battered server too hard then reduce the number of running threads. The lock objects ensure mutex and communication between the threads independent of how many threads are running.

Why are wait, notify and notifyAll methods of the class Object?

The fact that methods are inherited does not violate the Single Responsibility Principle. It could potentially violate the SRP if those methods could be overridden. But they cannot, they are declared final.

The SRP defines reponsibility

In the context of the Single Responsibility Principle (SRP) we define
a responsibility to be “a reason for change.” If you can think of more
than one motive for changing a class, then that class has more than
one responsibility.

The responsibility of managing concurrent programming with threads falls on the Object class which owns the implementation. There is no coupling between that responsibility and any other responsibility defined in Object or any of its subtypes. If you ever need to change the behavior of wait, you'll only need to change Object (and possibly any call site), not String, not List, not anything else.

You might want to argue that the Object class itself isn't very cohesive and tries to do too much: cloning, comparing objects for equality, generating a String representation, etc. One could then argue back that none of those things is coupled to the other, so it's not a problem.

Why do all Java Objects have wait() and notify() and does this cause a performance hit?

Well, it does mean that every object has to potentially have a monitor associated with it. The same monitor is used for synchronized. If you agree with the decision to be able to synchronize on any object, then wait() and notify() don't add any more per-object state. The JVM may allocate the actual monitor lazily (I know .NET does) but there has to be some storage space available to say which monitor is associated with the object. Admittedly it's possible that this is a very small amount (e.g. 3 bytes) which wouldn't actually save any memory anyway due to padding of the rest of the object overhead - you'd have to look at how each individual JVM handled memory to say for sure.

Note that just having extra methods doesn't affect performance (other than very slightly due to the code obvious being present somewhere). It's not like each object or even each type has its own copy of the code for wait() and notify(). Depending on how the vtables work, each type may end up with an extra vtable entry for each inherited method - but that's still only on a per type basis, not a per object basis. That's basically going to get lost in the noise compared with the bulk of the storage which is for the actual objects themselves.

Personally, I feel that both .NET and Java made a mistake by associating a monitor with every object - I'd rather have explicit synchronization objects instead. I wrote a bit more on this in a blog post about redesigning java.lang.Object/System.Object.

Why wait() and notify() are not in special class?

The real answer is that it was a mistake, finally acknowledged with the creation of the Condition class, which does exactly what you'd expect. (Although since it is an object, there is a possibility that you'll accidentally invoke wait() on it instead of await(), with hilarious consequences...)

Apart from the things you've already listed, tying a monitor to every single object also makes it impossible to have truly immutable objects in Java.

So you can do this for example:

class A {
void foo() {
synchronized((Integer)42) {
...
}
}
}

class B {
void foo() {
synchronized((Integer)42) {
...
}
}
}

Returning the same boxed integer for 42 every time shouldn't be a problem if the object was immutable. But it isn't, it has a mutable state: its monitor, making this kind of synchronization possible. What's particularly evil in this is that you've created a mutex between two pieces of code that on the face of it appear to be independent.



Related Topics



Leave a reply



Submit