You know these knowledge wait / notify of it?

We have two less commonly used (with more frame) of the method in the Java Object class: wait () and notify () or notfiyAll (), two methods are mainly used for co-processing among multiple threads, That control waits between threads, notifications, and wake-up switch.

Thread first understand which of several states, Java's Thread.State defined in six state of the thread, are as follows:

  1. NEW does not start and will not appear in the dump file (you can see the thread stack by jstack command)
  2. RUNNABLE JVM is executed
  3. BLOCKED is blocked, waiting to acquire a monitor lock to enter or re-enter the synchronized code block synchronized code block after the call Object.wait
  4. WAITING wait indefinitely for another thread after performing a specific action to wake it up, that is, the call will wait Object.wait have the same lock monitor thread calls notify / notifyAll to wake up
  5. TIMED_WAITING have time to wait for another thread to perform a particular action
  6. TERMINATED has completed execution

From the operating system level is concerned, during a process from creation to extinction, the most common process status for several new state: the transition process from the program image to image, has not added to the ready queue ready state: Everything is already running process ready, awaiting execution scheduled run state: process instruction being executed blocking state: process is waiting for a time to complete the operation, such as I / O operation to complete the state: the end of the process running, its resources have been released for use by other active processes use

Next, we analyze the following code

public class WaitNotify {

  public static void main(String[] args) {

    Object lock = new Object();
    
    // thread1
    new Thread(() -> {

        System.out.println("thread1 is ready");

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {

        }
        synchronized (lock) {
            lock.notify();
            System.out.println("thread1 is notify,but not exit synchronized");
            System.out.println("thread1 is exit synchronized");
        }


    }).start();

    // thread2
    new Thread(() -> {
        System.out.println("thread2 is ready");

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {

        }
        synchronized (lock) {
            try {
                System.out.println("thread2 is waiting");
                lock.wait();
                System.out.println("thread2 is awake");
            } catch (InterruptedException e) {
            }
        }
    }).start();
  }
}
复制代码

The above operating results following code

thread1 is ready
thread2 is ready
thread2 is waiting
thread1 is notify,but not exit synchronized
thread 1 is exit synchronized
thread2 is awake
复制代码

See here you will find unexciting, it seems to have no special thing, but if depth Analysis, you will find the following questions

  1. Why wait to call or notify sure to add synchronized, without okay?
  2. After thread2 call the wait, yet the current thread exits the synchronized block, another thread (thread1) can enter the synchronized block it?
  3. Why call wait () may throw an exception InterruptedException
  4. After waiting call notify / notifyAll in the thread will immediately wake you?
  5. Call to notify / notifyAll is randomly selected from a queue of waiting threads, or by taking a certain law to perform?
  6. Whether the wait thread can affect system performance?

For the above problem, take one down

Why wait to call or notify sure to add synchronized, without okay?

If you do not increase, you will get the following exception

Exception in thread "main" java.lang.IllegalMonitorStateException
复制代码

In the JVM source code first checks whether the current thread holds the lock, if no exception is thrown held

Second, how to increase, there are relatively extensive discussion, first wait / notify for communication, for this communication process is not interrupted between threads need to ensure atomicity wait / notify the entire block, it is necessary to add by synchronized lock.

After thread2 call the wait, yet the current thread exits the synchronized block, another thread (thread1) can enter the synchronized block it?

wait in the process temporarily release the synchronization lock (if you do not release the other thread there is no chance to grab), but it should be noted that when another thread calls notify evoke the thread of time, will re-acquire the lock before the wait method exits, only acquired the lock will continue, and this is consistent with our results, the output thread2 is awake, in fact, think also easy to understand, synchronized code is actually being surrounded by monitorenter and monitorexit up. When we call wait, it will release the lock, call monitorexit time will release the lock, then when thread2 wake up to the necessity to re-acquire the lock (objectMonitor :: enter).

In fact, from jdk source code ObjectMonitor :: wait method can see what will first have to give up to grab the lock (exit (self)), and give up to acquire locks on the premise that the lock

And will select the notify method to obtain a thread cpu executive power, to compete in the lock, if there is no competition to it will go to sleep.

If this code is called wait (200), it will be removed from the waiting set of threads after 200ms and allowed to compete again locks should be noted that notify method does not release the held monitor

Why call wait () may throw an exception InterruptedException

When we call the interrupt method of a thread, the threads will throw this exception, wait method do not want to destroy this rule, so even if the current thread because the wait has been blocked. When a thread wishes to continue it up when it was still recovering from blocking state to come, so wait method will be woken up in time to detect this state, when there is a thread interrupt it, and it will throw this abnormal recover from the blocked state.

There are two points to note:

  1. If the interrupt thread after just created, and did not start, enter the wait state waiting for him to start after that also will not be restored
  2. If the interrupt thread has a start, before entering the wait, if there is a thread calls its interrupt method, and that the wait did not equal what to do, come out directly, without blocking, the following code demonstrates this situation
Thread thread2 = new Thread(() -> {
    System.out.println("thread2 is ready");

    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {

    }
    synchronized (lock) {
        try {
            System.out.println("thread2 is waiting");
            lock.wait();
            System.out.println("thread2 is awake");
        } catch (InterruptedException e) {
            System.out.println(e);
        }
    }
});

  // main
  thread2.start();

  Thread.sleep(1000);
  thread2.interrupt();

复制代码

Code output below the above results

thread2 is ready
thread2 is waiting
java.lang.InterruptedException
复制代码

After waiting call notify / notifyAll in the thread will immediately wake you?

hotspot is the true realization of exit synchronized block of time to really wake up until the threads, but this is also the default policy can be changed in the wake immediately after notify the relevant thread. This can also be seen from objectMonitor class objectMonitor jdk :: notify the source process when the default policy is to notify the calling Policy == 2 (this value is the initial value in the source code, can -XX: Set SyncKnobs).

In fact, all of the ObjectWaiter collection objectMonitor removed for Policy (1,2,3,4) a waiting thread, put into _EntryList (blocked set of threads, can participate in the next grab lock), just put _EntryList strategy not the same, the rules embodied in the wake wait thread is not the same.

For after the default policy will notify the waiting thread into a set of threads blocked exits, because the synchronization block has not executing the monitorexit, in fact, has not yet released the lock, so print out "thread1 is exit synchronized!" When, thread2 or thread blocked state (yet because thread1 exit sync blocks).

Here it can be found not in the Policy for the case directly to a ObjectWaiter be unpark wake-up operation, but was awakened thread to acquire the lock immediately whether it? the answer is negative.

Call to notify / notifyAll is randomly selected from a queue of waiting threads, or by taking a certain law to perform?

We own realization of a for loop might get, but not so simple to achieve in jvm, but rather by means of a monitor_exit, I mentioned above, when a thread out of the recovery from the wait state, must first acquire the lock, and then exit sync blocks, the realization is calling notifyAll notify thread on exit its wake sync blocks from the last to enter the wait state of the thread, the thread exits the synchronization block of time to continue then wake up its penultimate thread into the wait state, and so, again this is a question of strategy, jvm provided one by one in the immediate wake of the thread parameters here should be divided:

  1. If it is to evoke through notify thread, that thread will wait before entering first to be aroused
  2. If the thread through evoke nootifyAll, the default is the last entry will first be aroused to that LIFO strategy

Whether the wait thread can affect system performance?

This is probably more concerned about the topic, as related to system performance issues, wait / nofity by jvm in the park / unpark mechanism to achieve, in linux this mechanism is through pthread_cond_wait / pthread_cond_signal play, so when a thread into a wait state, when in fact give up cpu, that this type of thread is not occupied cpu resources, it will not affect the system load.

What is a monitor (monitor)

Each object in Java can be a monitor (Monitor), which consists of a lock Monitor (Lock), a wait queue (waiting queue), a queue entry (entry queue) composition. A method for an object, if not synchonized keyword, which can be any number of threads, called at any time. A method for adding synchronized keyword, any time can only be won only one thread calls the object instance lock.

Enter the zone (Entry Set): represents the thread to acquire the object lock by synchronized requirements, if acquired, and then become the owner, if not obtained in waiting to enter the area until after the other thread releases the lock to go to the competition (who acquired it in accordance with )

Owner (Owner): indicates that the thread acquired the object lock, can execute code synchronized surrounded the

Waiting area (Wait Set): indicates that the thread calls the wait method, then release the held object lock, waiting to be awakened (who was awakened by the decision to acquire the monitor lock jvm)

About sleep

It is a static method invocation is generally Thread.sleep (2000), so that represents the current thread to sleep 2000ms, does not make the monitors, which require attention.

Your concern is my greatest support.

Guess you like

Origin juejin.im/post/5da03850e51d4577f706198b