3

Recently, I was asked in interview why wait, notify, and notifyAll are used. I explained them.

After that they asked me to assume an application is always single threaded. Is it really required? My answer was no.

Then, they asked why is design like wait, notify, and notifyAll are methods on the Object class. Why doesn't Java have an interface and these methods are in that interface and which ever class wants to implement it can use it. So, I was kind of stuck and unable to think over this design. Can anyone please sow light over this?

3

4 Answers 4

2

JVM uses OS-level threads. That means that each concrete JVM for each concrete OS handles threads differently. And these methods are not only implemented in Object class, they are marked as native, which kind of means that the are implemented in system layer of JVM.

And if those methods were in some interface, that would mean that anybody can redefine them.

Sign up to request clarification or add additional context in comments.

Comments

0

Wait and notify and notifyAll is not just normal methods or synchronization utility, more than that they are communication mechanism between two threads in Java. And Object class is correct place to make them available for every object if this mechanism is not available via any java keyword like synchronized. Remember synchronized and wait notify are two different area and don’t confuse that they are same or related. Synchronized is to provide mutual exclusion and ensuring thread safety of Java class like race condition while wait and notify are communication mechanism between two thread.

Comments

0

Then, they asked why is design like wait, notify, and notifyAll are methods on the Object class. Why doesn't Java have an interface and these methods are in that interface and which ever class wants to implement it can use it.

All of these methods are implemented in native code and they integrate closely with the synchronized block that wraps them. They are part of the Java language definition and have specific behaviors that programmers rely on. It would not be appropriate for them just to be interface methods that any object would implement.

When one object calls obj.wait(); on another object, it doesn't have to worry about the implementation of wait. It needs to make sure that it has a mutex lock on that object so it can make critical updates to it or other storage and if the wait method was implemented by the object itself, then that object could violate the language requirements and, for example, allow multiple threads into the protected block at the same time. A thread can synchronize and call wait/notify/notifyAll on another object or not without having to worry about whether or not that object has implemented those methods appropriately. By making them final methods on Object the behavior will work the same regardless of the object type or local implementation.

Also, as I mentioned, wait/notify/notifyAll are integrated closely with the surrounding synchronized block. When a thread is blocked in wait() the surrounding synchronized lock is released so that other threads can get access to the protected block. This coordination would not be possible if the wait() was just a simple method call without other strange language features.

This reminds me of my other answer here: Concept behind putting wait(),notify() methods in Object class

8 Comments

I would say that the consensus - at least in compiler circles - is that allowing every object to be used for synchronization was a costly mistake, particularly considering best practices for synchronization (use final object to make sure the lock can't be leaked). There's not many good arguments against providing an explicit lock class (an interface would indeed be a weird choice since there's only limited extensibility that makes sense) that enables these features really. Don't you agree?
Sorry but I don't agree. How is it "costly" if you don't have to use it? Everyone is so anti-synchronized when I'd rather the JVM be efficient at supporting it – maybe using the same Lock objects that people want to do by hand. I want to write and maintain less code and teach my junior programmers to use the language features instead of Lock objects directly unless I have to @Voo.
Because the JVM has to support locks in object headers for every single object despite only 0.0..01% of all objects will ever actually make use of it. Now HotSpot in particular goes to great lengths to minimize the associated overhead, but that complexity has costs of its own: There have been many intricate bugs in that part of the code.
And as I said best practice is to create a separate object just for locking anyhow. The difference between private final Object lock = new Object() and private final Lock lock = new Lock() is minimal at best, would clearly separate responsibilities, would avoid a source of bugs and bad design for beginners and would allow a great amount of customization.
Just because there is code supported by the JRE/JVM to create a lock per object doesn't mean that there is an impact on the object in memory @Voo. You don't get a monitor or a lock associated with the object unless you call synchronized on it. I can see a number of ways that it would be as expensive as new Lock() on demand.
|
0

It was a design goal from the start that Java programs would be multithreaded. Remember the plan was for Java to make embedded programming less intimidating, the whole serverside web application thing (leading to the commoditization of Sun's core business) was an accident.

Since the goal was to enable creating embedded applications that would talk to other devices, it had to be multithreaded in order to be network-friendly and event-driven. But writing efficient multithreaded servers wasn't high on the list for java.

Java didn't have ReentrantLock or nonblocking i/o for a long time. Initially the main data structures available were Vector, Hashtable, and StringBuffer (all of which had synchronized on all public methods). From that choice it seems like the goal was good-enough, as opposed to being as efficient as possible. Later on it was clear Java needed to be more efficient for the use case of server applications and 1.2 introduced equivalents of Vector and Hashtable that were unsynchronized. This seemed like an afterthought, a course adjustment made once it was apparent Java had a new role it wasn't previously designed for.

If Java had stayed in the niche it was created for then possibly intrinsic locks might have been adequate. It seems the initial plan was for intrinsic locks only, so that the lock might as well be wired into the Object.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.