多线程—wait/notify

重难点:理解object和线程之间的关系以及wait、notify、notifyAll的调用者和调用时刻。

原理:

 相关方法:

  1. 首先需要明确是:下面三个方法都是属于,synchronized锁的那个对象的,因此不管是在哪里出现这几个方法,都应该是那个对象来调用这三个方法,对象是调用者,线程不是。

  2. 其次就是Monitor和对象之间的关系,java对象的对象头里面的Mark Work指向Monitor(Java环境看不到,属于操作系统),每个对象关联一个Monitor。

  3. obj.wait()让进入object监视器(object指向的Monitor)的线程拥有者到waitSet等待。

  4. wait常用的方法是一个带参数一个不带参数,不带参数的底层是使用带参数的实现的,参数传的是0。wait()和wait(0)意思相同,都为一直等待。

  5. obj .notify()在object指向的Monitor上正在waitSet等待的线程中随机挑一个唤醒,然后进入EntryList竞争。

  6. obj.notifyAll() 让object指向的Monitor上正在waitSet等待的线程全部唤醒,然后进入EntryList竞争。

  7. wait()和notify()的基本使用格式:

synchronized(obj){
    while(条件不成立){
     	obj.wait()   
    }
    //干活
}
synchronized(lock){
    lock.notifyAll();
}

注意:

  1. 它们都是线程之间进行协作的手段,都属于Object对象的方法必须获得此对象的锁,才能调用这几个方法。

  2. 如果没有获取到对象锁,直接调用上面三个方法,会抛出异常(java. lang .IllegalMonitorStateException)

    注意中第一点的演示,结合原理中的图理解。

@Slf4j
public class Thread1 {
    private static int current;
    private static Object object = new Object();
    public static void main(String[] args) throws InterruptedException {
        Thread t2 = new Thread(()->{
            log.debug("线程2开始");
            //获取object对象锁
            synchronized (object){
                log.debug("线2程进入等待");
                try {
                    //让线程t2等待,进入Monitor的waitSet等待,状态变为WAITING状态,并且释放对象锁
                    object.wait(0); //这里的wiat(0)和wait()方法一样效果。
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                current = 100;
            }
            //当线程2被唤醒之后,执行下面的代码
            log.debug("线程2被唤醒了");
            log.debug("current:"+current);
            log.debug("线程2返回");
        },"t2");
        Thread t1 = new Thread(()->{
            log.debug("线程1开始");
            synchronized (object){
                log.debug("线程1获取到锁");
                current = 101;
            }
            log.debug("current:"+current);
            log.debug("线程1返回");
        },"t1");
        t2.start();
        t1.start();
        Thread.sleep(3000);
        synchronized (object){
            //只有获取到对象锁之后,才能使用对象的notifyAll方法
            object.notifyAll();
        }
    }
}

最后看看,sleep(long n)和 wait(long n)的区别

  1. sleep是Thread的方法,而wait是Object的方法。

  2. sleep不需要强制和synchronized配合使用,但wait需要和synchronized一起用。

  3. sleep在睡眠的同时,不会释放对象锁的,但wait在等待的时候会释放对象锁。

  4. 相同点是:调用它们之后,线程的状态是一样的,都是TIMED_WAITING。

おすすめ

転載: blog.csdn.net/qq_42251944/article/details/120865002