[Multithreading] Wait and Notify analytical method

How a wait / notify use

  wait \ notify these two methods is a method of the Object class, these two methods including their overloaded method, a total of five, and the Object class method in a total of only 12, showing the importance of these two methods. Let's look at the code in the JDK:

public final native void notify();
public final native void notifyAll();
public final void wait() throws InterruptedException {
    wait(0);
}
public final native void wait(long timeout) throws InterruptedException;
public final void wait(long timeout, int nanos) throws InterruptedException {
    if (timeout < 0) {
        throw new IllegalArgumentException("timeout value is negative");
    }
    if (nanos < 0 || nanos > 999999) {
        throw new IllegalArgumentException("nanosecond timeout value out of range");
    }
    if (nanos > 0) {
        timeout++;
    }
    wait(timeout);
}

  There are three methods of native, i.e. a virtual machine executed by the native code c. There are two wait overloaded method eventually calls the wait (long) method.

  Above all, know how. To a simple example of how to use these methods.

public  class WaitNotify {
     Private  Final  static Object Lock = new new Object ();
     public  static  void main (String [] args) {
         new new the Thread (() -> { 
            System.out.println ( "A waiting thread take lock" );
             the synchronized (lock) {
                 the try { 
                    System.out.println ( "a thread got locked" ); 
                    TimeUnit.SECONDS.sleep ( . 1 ); 
                    System.out.println ( "thread a starts waiting for a lock and discard"  );
                    lock.wait ( ); 
                    System.out.println ( "A thread may continue to execute the notification continues to run to completion" ); 
                } the catch (InterruptedException ignored) { 
                } 
            } 
        }, "thread A" ) .start ();
         new new the thread (() -> { 
            System.out.println ( "thread B waiting for a lock" );
             the synchronized (lock) { 
                System.out.println ( "get locked thread B" );
                 the try { 
                    TimeUnit.SECONDS.sleep ( . 5 ); 
                } the catch ( InterruptedException ignored) {
                } 
                Lock.notify (); 
                System.out.println ( "B random inform a thread thread Lock object" ); 
            } 
        }, "thread B" ) .start (); 
    } 
}

  In the above code, the thread will grab the A and B locks the lock object, the better luck A (B may also get a lock), he first got the lock, and then call the wait method, gave up the lock, and hang himself, this time waiting for the lock B got the lock, and then informed the a, but please note that after the notification is completed, B thread does not execute code complete synchronization code block, therefore, a still can not get a lock and therefore can not run, B thread execution until completion, out of sync block, this time a thread is activated to continue.

  The method of using wait and notify methods allows two independent threads communicate. Also face questions is often mentioned how communication between threads .

  If you do not wait method and noitfy method, how do we get two threads communicate it? The simplest way is to make a thread loop to check a tag variables, such as:

  while (value != flag) {
    Thread.sleep(1000);
  }
  doSomeing();

  The code above does not satisfy the conditions in the sleep period of time, so do the purpose is to prevent excessive "invalid attempt", this approach appears to be able to achieve the required functionality, but the following problems:

  1. Difficult to ensure timeliness. Since 1000 the waiting time will lead to the time difference.
  2. Difficult to reduce the cost, if ensure the timeliness, shorter sleep time, it will greatly consume CPU.

  But with Java native method wait and notify methods, everything solved. The official argument is waiting / notification mechanism. A thread is waiting, another thread may notice this thread, it enables communication between threads.

Why do we have two in the synchronized block

  Note, wait \ use notify method must be in synchroized sync block and the sync blocks in the current object, if you call the B object wait or notify method A method in object, the virtual machine throws IllegalMonitorStateException, illegal surveillance is an exception, because this thread is not an object you hold your monitor and call monitor.

  So why these two methods must be in sync block it?

  Here to say a technical term: race conditions. What is race conditions?

When two threads competing for the same resources, if the order of access to sensitive resources, is said to exist race conditions.

  Race conditions can cause some bugs in the program of concurrency. Multithreading some resources will have competition when race conditions, if the program fails to execute first competition discharged later executed, then the whole program there will be bugs some uncertain.

  This is difficult to find bugs and will be repeated, because the competition will be randomly between threads.

  Suppose there are two threads, namely producers and consumers, they have their own tasks.

    1.1 Producers inspection conditions (such as the cache is full) -> 1.2 Producers must wait

    Consumer spending up 2.1 of a unit of the cache -> 2.2 Reset conditions (such as cache is not full) -> 2.3 calls notifyAll () Wake producers

  We hope the following order: 1.1> 1.2> 2.1> 2.2> 2.3

  However, due to CPU execution is random, may lead to execution 2.3, the implementation of 1.2, which would lead to the producer never wake up to!

  Therefore, we must manage to process, i.e. synchronization, we can manually adjust the execution sequence of threads by binding sync block and wait and notify methods.

Three using wait \ notify simple model of production and consumption

1 defined resources

/ ** 
 * resource 
 * / 
public  class the Resource { 

    / * resource ID * / 
    Private  int Number = 0 ;
     / * resource identifier * / 
    Private  Boolean In Flag = to false ; 

    / ** 
     * production resources 
     * / 
    public  the synchronized  void Create () {
         IF (Flag) { // first determine whether the mark has produced, if production has been waiting for the consumer; 
            the try { 
                the wait (); // make production thread waiting 
            } the catch (InterruptedException E) {  
                e.printStackTrace ();
            } 
        } 
        Number ++; // produce a 
        System.out.println (Thread.currentThread () getName () + " producer -----------------------" +. Number); 
        In Flag = to true ; / / resources have been produced to mark 
        the Notify (); // wake-up thread (queue) waiting for the operating resources 
    } 

    / ** 
     * consumer resources 
     * / 
    public  the synchronized  void the destroy () {
         IF (! {Flag)
             the try { 
                the wait () ; 
            } the catch (InterruptedException E) { 
                e.printStackTrace (); 
            } 
        }
        System.out.println(Thread.currentThread().getName() + "消费者****" + number);
        flag = false;
        notify();
    }
}

2 producer

/**
 * 生产者
 */
public class Producer implements Runnable {

    private Resource resource;

    public Producer(Resource resource) {
        this.resource = resource;
    }

    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            resource.create();
        }

    }
}

3 Consumers

/**
 * 消费者*/
public class Consumer implements Runnable {

    private Resource resource;
    public Consumer(Resource resource) {
        this.resource = resource;
    }
    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            resource.destroy();
        }
    }
}

  Basically has the following classic rules of producers and consumers modes:

  Wait for the party to the following rules:

    1. Obtain the lock object.

    2. If the conditions are not met, then call the object's wait method, after being notified still checking conditions.

    3. respective logic condition is satisfied is executed.

  Into the corresponding pseudo-code:

synchroize (Object) {
     the while (the condition is not satisfied) { 
      Object .wait (); 
    } 
    corresponding to the processing logic ...... 
}

  Notify Party to the following rules:

    1. The key is to get the object.

    2. changing conditions.

    3. Inform all threads waiting on the object.

Corresponding to the following pseudo-code:

the synchronized (object) { 
  change condition 
  objects .notifyAll (); 
}

Four underlying principles

  Know how to use, you have to know what his principles in the end is?

  First we look at, what order to use these methods generally?

    We need to call to lock objects 1. Using the wait, notify and notifyAll.

    2. The method calls wait, the thread status has changed to Running Waiting, and placed in the current thread object  wait pool .

    After the 3. notify or notifyAll method call, still waiting thread does not return from a wait, require the calling thread releases the lock noitfy, waiting for a chance to return to the thread from the wait.

    4. notify method waits a waiting queue thread moves from the wait queue latch cell types, and sucked notifyAll method waits pool species move all locks all threads in the pool, is moved by the thread state changes Waiting Blocked .

    The premise returned from the wait method is thread into the lock pool from waiting pool, then get the calling object lock.

  You can see from the above details, waiting / notification mechanism relies on the synchronization mechanism, its purpose is to ensure that the waiting thread from the wait method returns can pick up changes made to the notification thread variables.

The figure depicts the above procedure:

  

 

reference:

  https://www.cnblogs.com/aiqiqi/p/10982028.html#_label3_1

 

Guess you like

Origin www.cnblogs.com/aiqiqi/p/11668211.html