儿时的游戏:(等待 与 唤醒) 

  有一群小朋友一起玩一个游戏,这个游戏可能大家都玩过,大家一起划拳,划拳输得最惨的那个小朋友去抓人(这个小朋友取名为 CPU),被抓的很多人取名为线程,有很多线程,如果其中一个小朋友(例如:Thread-3) 被木头了(wait();)  就站着不准动了(冻结状态),Thread-3小朋友站着不动(冻结状态) CPU小朋友就不会去抓Thread-3小朋友,因为Thread-3小朋友(释放CPU执行资格)   需要其他小朋友(例如:Thread-5) 去啪一下Thread-3小朋友(notify();),  此时Thread-3小朋友就可以跑了(被唤醒) 此时Thread-3小朋友具备被抓的资格(具备CPU执行资格),能否被抓得到 要看CPU小朋友的随机抓人法(CPU切换线程的随机性)

 

等待唤醒机制: 

   wait(); 等待/冻结 :可以将线程冻结,释放CPU执行资格,释放CPU执行权,并把此线程临时存储到线程池

   notify(); 唤醒线程池里面 任意一个线程,没有顺序;

   notifyAll(); 唤醒线程池里面,全部的线程;

 

使用等待唤醒注意事项:

  1.使用来wait();冻结,就必须要被其他方notify();,否则一直wait()冻结,所以等待与唤醒是配合一起使用的;

  2.wait();  notify();  notifyAll(); 等方法必须被synchronized(锁) {包裹起来},意思就是:wait();  notify();  notifyAll();  必须要有同步锁🔒,否则毫无意义;

    3.wait();  notify();  notifyAll(); 等方法必须持有同一把锁🔒,因为:lockA.wait();  只能使用 lockA.notify(); / lockA.notifyAll(); , 它们是使用同一把锁🔒的;

 

等待:🔒锁.wait();

唤醒:🔒锁.notify();

唤醒:🔒锁.notifyAll();

 

代码分析 1:

❌❌❌❌❌ 错误的示范,public synchronized (锁🔒== this) void testMethod1(){} ,然后却是OBJ_LOCK.notify();     this锁🔒和 OBJ_LOCK🔒不一致,是错误的,没有共用一把锁

private final Object OBJ_LOCK = new Object();
    
    /**
     * public synchronized void testMethod1(){}
     * synchronized的锁🔒是this /  b = new TestWaitNotifyDemo(); b也是
     * 所以可以:this.notify();    this.notifyAll();    this.wait();
     */
    public synchronized void testMethod1() {

        /**
         * 唤醒 wait(); 冻结的线程,如果没有就是空唤醒,Java是支持的
         */
        OBJ_LOCK.notify(); // 注意:⚠️ wait();  notify();  这些必须要有同步锁包裹着

        /**
         * 唤醒所有
         */
        OBJ_LOCK.notifyAll(); // 注意:⚠️ wait();  notify();  这些必须要有同步锁包裹着

        /**
         * 当前自己线程 冻结,释放CPU执行资格,释放CPU执行权,CPU就会去执行其他线程了
         */
        try {
            OBJ_LOCK.wait(); // 注意:⚠️ wait();  notify();  这些必须要有同步锁包裹着
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

 

✅✅✅✅✅,正确的方式:public synchronized(🔒锁==this) void testMethod1, this.notify();  this.notifyAll();  this.wait(); 

/**
     * public synchronized void testMethod1(){}
     * synchronized的锁🔒是this /  b = new TestWaitNotifyDemo(); b也是
     * 所以可以:this.notify();    this.notifyAll();    this.wait();
     */
    public synchronized void testMethod1() {

        /**
         * 唤醒 wait(); 冻结的线程,如果没有就是空唤醒,Java是支持的
         */
        this.notify(); // 注意:⚠️ wait();  notify();  这些必须要有同步锁包裹着

        /**
         * 唤醒所有
         */
        this.notifyAll(); // 注意:⚠️ wait();  notify();  这些必须要有同步锁包裹着

        /**
         * 当前自己线程 冻结,释放CPU执行资格,释放CPU执行权,CPU就会去执行其他线程了
         */
        try {
            this.wait(); // 注意:⚠️ wait();  notify();  这些必须要有同步锁包裹着
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

 

代码分析 1 伪代码:

   public synchronized(🔒锁是this) void testMethod1() {

       
        锁🔒this.notify(); // 注意:⚠️ wait();  notify();  这些必须要有同步锁包裹着

        
        锁🔒this.notifyAll(); // 注意:⚠️ wait();  notify();  这些必须要有同步锁包裹着

        
        锁🔒this.wait(); // 注意:⚠️ wait();  notify();  这些必须要有同步锁包裹着
        

    }

 

 


 

 

 

代码分析 2:

错误的示范❌❌❌❌❌❌❌❌❌❌❌❌❌❌❌❌❌❌❌❌❌  synchronized (锁🔒== OBJ_LOCK) ,然后却是this.notify();  this锁🔒和 OBJ_LOCK🔒不一致,是错误的

private final Object OBJ_LOCK = new Object();

    public void testMethod2() throws InterruptedException {

        /**
         * synchronized (OBJ_LOCK) {}
         * synchronized的锁🔒是 OBJ_LOCK
         * 所以可以:OBJ_LOCK.notify();    OBJ_LOCK.notifyAll();    OBJ_LOCK.wait();
         */
        synchronized (OBJ_LOCK) {

            /**
             * 唤醒 wait(); 冻结的线程,如果没有就是空唤醒,Java是支持的
             */
            this.notify(); // 注意:⚠️ wait();  notify();  这些必须要有同步锁包裹着

            /**
             * 唤醒所有
             */
            this.notifyAll(); // 注意:⚠️ wait();  notify();  这些必须要有同步锁包裹着

            /**
             * 当前自己线程 冻结,释放CPU执行资格,释放CPU执行权,CPU就会去执行其他线程了
             */

            this.wait(); // 注意:⚠️ wait();  notify();  这些必须要有同步锁包裹着

        }
    }

 

正确的示范✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅synchronized (锁🔒== OBJ_LOCK) ,然后是OBJ_LOCK.notify();  使用了同一把OBJ_LOCK锁🔒,是正确的✅

private final Object OBJ_LOCK = new Object();

    public void testMethod2() throws InterruptedException {

        /**
         * synchronized (OBJ_LOCK) {}
         * synchronized的锁🔒是 OBJ_LOCK
         * 所以可以:OBJ_LOCK.notify();    OBJ_LOCK.notifyAll();    OBJ_LOCK.wait();
         */
        synchronized (OBJ_LOCK) {

            /**
             * 唤醒 wait(); 冻结的线程,如果没有就是空唤醒,Java是支持的
             */
            OBJ_LOCK.notify(); // 注意:⚠️ wait();  notify();  这些必须要有同步锁包裹着

            /**
             * 唤醒所有
             */
            OBJ_LOCK.notifyAll(); // 注意:⚠️ wait();  notify();  这些必须要有同步锁包裹着

            /**
             * 当前自己线程 冻结,释放CPU执行资格,释放CPU执行权,CPU就会去执行其他线程了
             */

            OBJ_LOCK.wait(); // 注意:⚠️ wait();  notify();  这些必须要有同步锁包裹着

        }
    }

 

代码分析 2   伪代码:

  private final Object OBJ_LOCK = new Object();

    public void testMethod2() throws InterruptedException {

        synchronized (OBJ_LOCK🔒锁) {

            /**
             * 唤醒 wait(); 冻结的线程,如果没有就是空唤醒,Java是支持的
             */
            OBJ_LOCK🔒锁.notify(); // 注意:⚠️ wait();  notify();  这些必须要有同步锁包裹着

            /**
             * 唤醒所有
             */
            OBJ_LOCK🔒锁.notifyAll(); // 注意:⚠️ wait();  notify();  这些必须要有同步锁包裹着

            /**
             * 当前自己线程 冻结,释放CPU执行资格,释放CPU执行权,CPU就会去执行其他线程了
             */

            OBJ_LOCK🔒锁.wait(); // 注意:⚠️ wait();  notify();  这些必须要有同步锁包裹着

        }
    }