notify/wait
(pessimistic locking) is usually a specific requirement of the task, i.e. it is required to implement already existing BlockingQueue.Along with
synchronized
, these methods constitute the lowest level of pessimistic locking in Java, used internally in the implementation of synchronization primitives. Since Java 5, there has been no need to use these methods directly, but theoretical knowledge of them is often still required in interviews.To call these methods on an object, its monitor must be acquired, i.e., the call must be within a synchronized block on that object. Otherwise, an
IllegalMonitorStateException
is thrown. Therefore, a complete answer requires understanding how a monitor lock (synchronized
block) works.Calling
wait
pauses the current thread on this object and releases its monitor. Execution resumes when another thread calls notify
and releases the monitor lock. If multiple threads are waiting on the object, notify
wakes up a random one, while notifyAll
wakes them all at once.Theoretically, a
wait
can be interrupted without a notify
call, at the discretion of the JVM (spurious wakeup). While this is extremely rare in practice, it's prudent to add another check for the condition to terminate the wait after calling wait
.Two other abnormal ways to end
wait
are external thread interruption and a timeout. An InterruptedException
is thrown in case of an interruption. For a timeout, the wait time must be specified as a method parameter. A value of 0 will be ignored.Various issues with implementing locks are discussed in Java Concurrency in Practice 14.1.3, 14.2.