preface

The last section describes the principle and optimization analysis of Synchronized keywords, while the other two keywords used with Synchronized wait¬ify are the focus of this chapter. The simplest things often contain the most complex implementation, because it needs to provide a stable foundation for the existence of the upper layer, Object as the base class of all objects in Java, its existence value is self-evident, wait&notify method realization of multi-threaded cooperation to provide a guarantee.

1 source

Today we are going to look at two methods, wait&notify, in the Object class. There are five wait&notify methods, and there are only 12 wait&notify methods. Let’s start with the code in the JDK:





Those are the five ways. Three of these methods are native, meaning they are executed by the VIRTUAL machine’s native C code. Two wait overloading methods ended up calling wait (long) anyway.


1. Wait method: Wait is to release the object lock and enter the wait pool. To release an object lock, you must acquire the lock first. So wait must be written in a synchronized block, or an exception will be reported.



2. Notify method: it also needs to be written in the synchronized code block. These two methods of calling the object also need to obtain the lock of the object first. Notify, notifyAll: Wakes up the thread waiting for the synchronization lock of the object and puts it into the lock pool of the object. Threads in the lock pool of an object can compete for the object lock and then execute it.




Another important point is that calls to notify and notifyAll do not release object locks. For example:




NotifyAll is called, but then an infinite loop is entered. As a result, the critical section cannot be released and the object lock cannot be released. So, even if it wakes up all the threads in the wait pool into the lock pool of the object, none of the threads in the lock pool will run because they never get the lock.

2 the usage

A simple example:





Execution Result:






Prerequisite: The wait and notify methods must be called from the same LOCK object




What is the relationship between the lock object, thread A, and thread B? Based on the above conclusion, imagine a scenario:




3 Related questions

3.1 Why must WAIT ¬ify Add synchronized lock

Implementation-wise, this lock is the key to making wait/notify work, and I think it’s possible to implement a similar mechanism in other ways, but hotspot at least relies entirely on this lock to implement wait/notify.






Synchronized code blocks contain monitorenter and Monitorexit directives in the bytecodes generated by javap. As shown below:




Bytecode generated by javAP


Monitorenter fetches the object’s monitor, while lock.wait() is implemented by calling native wait(0).




Indicates that a thread executing the lock.wait() method must hold the lock object’s monitor. If the wait method is executed in synchronized code, the thread obviously already holds the monitor.

3.2 Why may the WAIT method Throw InterruptedException

This exception everyone should know, when we call a thread when the interrupt method, the corresponding thread will throw this exception, also don’t want to break the rule, and then wait wait has been blocked because it is over, so even if the current thread when a thread hope it up and continue to execute, it still have to recover from the blocking state, So the wait method detects this state when it is awakened, and when an interrupt interrupts it, it throws an exception to recover from the blocking state.

Two things to note here:





3.3 Wake up the thread immediately after notify

The actual implementation in hotspot is to wake up the corresponding thread only when the block is out of sync, but this is the default policy and can be changed to wake up the relevant thread immediately after notify.

3.4 How does a notifyAll approach all threads

It’s not as simple as monitoreXit, which uses monitorexit to acquire the lock and exit the synchronization block when a thread returns from wait. So a notifyAll is implemented when the thread that calls notify wakes up the last thread to wait when it exits its block, and then wakes up the penultimate thread to wait when it exits the block, and so on. Again, this is a matter of policy. The JVM provides parameters that directly wake up threads, but these are rare enough to omit.

3.5 Whether Load Is Affected by Wait threads

Wait/Nofity is implemented by the PARK /unpark mechanism in the JVM, and in Linux by the park/unpark mechanism

Pthread_cond_wait /pthread_cond_signal, so when a thread enters the wait state, it actually abandons the CPU, meaning that it does not consume CPU resources