wait-notify/notifyAll

先说例子,再说原理。

等待/通知机制:在某个条件下等待,当条件满足时,通过它结束等待,继续执行。

简单实现:

等待方:

public class Waiter {



    public static volatile int flag = 0;



    public static void setFlag(int flag) {

        Waiter.flag = flag;

    }



    public static void waitMethod() throws InterruptedException {

        System.out.println("进入");

        while (flag == 0) {

            //避免频繁的执行判断条件

            Thread.sleep(1000);

        }

        System.out.println("因为值被修改所以执行结束");

    }

}

通知方:

public class Notifyer {

    public static void notifyMethod(int i) {

        Waiter.setFlag(i);

    }

}

 

上述等待通知机制是不是很low

1、需要满足volatile的使用条件

2、难以保证及时性

3、CPU资源浪费

 

 

Java内置方式:

等待方:

public class Waiter {

     private Object lock;

   

     public Waiter(Object lock) {

        this.lock=lock;

    }



    public void waitMethod() throws InterruptedException {

        System.out.println("进入");

        synchronized (lock) {

               lock.wait();

        }

        System.out.println("因为被唤醒所以执行结束");

    }

}



通知方:

public class Notifyer {



    public Object lock;



    public Notifyer(Object lock) {

        this.lock=lock;

    }



    public void notifyMethod() {

        synchronized (object) {

           lock.notify();

        }

    }

}

 

前提:1、调用wait,notify前必须对对象进行加锁,否则编译可以通过,运行保错java.lang.IllegalMonitorStateException    稍后解释

            2、必须先wait(),然后notify()。否则一直wait下去。

 

在简单实现中,我们做了一些什么?

1、volatile的变量,保证一个线程修改后,另外一个线程可以看到更新后的值

2、sleep    避免频繁执行判断条件

 

wait,notify做了什么?

1、首先我们没有看到等待条件,以及修改条件的操作

2、其次wait方法执行后会释放锁,执行它的线程进入了waiting状态

3、最后 notify方法执行,使得线程继续执行。

说明wait,notify中隐式的设置了条件,修改了条件,同时提高利用率。

 

原理:

        wait:首先获取锁对象

                   然后调用了对象的wait()方法,释放锁并进入了对象的监视器的等待队列WaitQuere中。

 

                   关于对象监视器的说明

                   为什么是进入对象的监视器的等待队列WaitQuere中呢?

                   答:1、在不加锁的时候反馈的异常是IllegalMonitorStateException,非法的监视器状态。嗯...这应该可以说明一下问题

                           2、高级玩家阔以去搞搞源码。objectMonitor.hpp

                   试想一下,如果不加锁,那么如何获取锁对象的监视器,如何进入监视器对象的等待队列。

        

          notify/notifyAll:首先获取锁对象

                    然后调用对象的notify方法,将监视器对象中WaitQueue队列中等待的线程移到监视器的 SynchronizedQueue队列中。(这一步就相当于是简单实现中的修改条件), 此时线程状态变为阻塞状态。最后释放锁,监视器同步队列中的线程再次获取到锁并从wait()方法返回继续执行(说明notifyAll唤醒是随机的)。

 

核心:获取监视器,利用监视器的等待队列,同步队列

你可能感兴趣的:(并发,并发,wait,notify,notifyAll)