Wait-notify scene
The typical Wait-notify scene is generally related to the following two contents:
1. State variable
When threads need Wait, it is always caused by some conditions. For example, filling in the queue, when the queue element is full, the thread needs to stop running. When the queue elements are vacant, continue their own execution.
2. Condition Predicate
When the thread is determined whether to enter the Wait or wakes up from Notify, it is necessary to test whether the status conditions are met. For example, adding elements to the queue, the queue is full, so it blocks the current thread. When other threads take off the element from the queue, the "queue has the remaining space in the queue, which can be added to the waiting thread." At this time, the process of waiting for the element will be awakened, and then judge whether there is really room for the current queue. If there is really remaining space, add the element in. If not, continue to block and wait for the next wake -up.
3. Condition queue
Each object has a built -in condition queue. When a thread calls the WAIT function on the object, the thread will be added to the condition queue of the object.
Notice
Wait and Notify are an important part of the Java synchronization mechanism. Combined with the use of Synchronized keywords, many excellent synchronous models can be established, such as producer-consumer model. But when using the function (), notify (), notifyall () function, you need to pay special attention to the following points:
Wait (), notify (), notifyall () methods do not belong to the Thread class, but belong to the Object foundation class, that is, each object has the functions of Wait (), notify (), and notify (). Because each object is locked, the lock is the basis of each object, so the method of operating lock is also the most basic.
Call Obj's Wait () and notify () method, you must get the OBJ lock, that is, you must be written in the synchronized (obj) {...} code segment.
After calling obj.wait (), the thread A releases the lock of ObJ, otherwise the thread B cannot obtain the OBJ lock, and it will not be able to wake up thread A in the synchronized (obj) {...} code segment.
When the obj.wait () method returns, thread A needs to get the OBJ lock again to continue execution.
If threads A1, A2, A3 are in obj.wait (), the thread B calls obj.notify () can only wake up one of the threads A1, A2, A3 (which one is determined by JVM).
If thread B calls obj.notifyall (), he can all wake up the waiting thread A1, A2, A3, but the waiting thread to continue to execute the next sentence of obj.wait (), you must get an obj lock. Therefore, threads A1, A2, A3 only have only one chance to obtain locks and continue to execute. For example, A1, the rest needs to wait for the A1 to release the OBJ lock before continuing to execute.
When thread B calls obj.notify () or obj.notifyall (), thread B is holding the OBJ lock. Therefore, thread A1, A2, A3 is awakened, but the OBJ lock cannot be obtained. Until the thread B exit the synchronized code block and release the OBJ lock, one in the thread A1, A2, A3 has the opportunity to get the object lock and continue to execute.
For example code
The typical code structure of the thread's wait operation is as follows:
public void test () throws interruptedException {synchronized (obj) {While (! ConTidition) {obj.wait ();}}}}}}}}}
Why do obj.wait () operations must be located in the cycle? There are several main reasons:
1. An object lock may be used to protect multiple state variables. When they all need Wait-notify operation, there will be problems if they do not put the Wait in the WHILE cycle. For example, a certain object locks OBJ to protect the two status variables A and B. When the conditions of A assertion are not established, the Wait operation occurs. When the condition of B is assertive, the WAIT operation occurs. In the queue. Now if a operation of a state variable A occurs, the NOTIFYALL operation is called on OBJ, then all threads in the condition queue corresponding to OBJ are awakened. However, B's conditions for the assertion of B must not be established, and the thread waiting for B is also awakened at this time, so you need to recycling whether the condition of B is met to be met.
2. The conditions of the same state of multiple threads are asserted. For example, the scene of adding elements to the queue, the current queue is full, and multiple threads want to add elements inside, so they are all. At this time, another thread took out an element from the queue and called the notifyAll operation to wake up all threads, but only one thread could add a element to the queue. Others still need to wait.
3. False awakening. Without being notified, interrupt orout, the thread was automatically awakened. Although this situation rarely occurs in practice, this situation can be eliminated through cycle waiting.