为什么wait()和notify()必须放到一个loop:synchronized中!!!

依靠对象

(wait()要知道等下被谁唤醒,notify()要知道去唤醒谁;所以wait()和notify()需要依靠同一个对象来调用)

需要监视器

这就需要一个监视器: 包含一个对象锁、一个等待队列、一个同步队列

  • 对象锁:同一时间只能被一个线程获得,保证只有一个线程中的同步代码块被执行
  • 等待队列:使用wait() 方法后被阻塞的线程会放到此队列中,这些线程待唤醒
  • 同步队列:存放竞争同步资源的线程

过程解释

notify() 的过程其实就是:将等待队列的某个线程调到同步队列中的过程

wait() 的过程其实就是:将同步队列中的本线程主动放到等待队列中的过程

例子

通过一个生产者-消费者例子来解释,没有同步代码块可能出现的情况:

         消费者刚判断完集合为空,没来得及wait()(判断-执行没有形成原子操作) ,就被阻塞;cpu跑去执行生产者生产,生产完调用notify,但此时监视器中并没有处于wait的线程,不起作用;cpu又来执行wait();如果后面生产者长时间不生产(没有调用notify),那么会导致生产者生产了,但消费者还在长时间等待(阻塞)中,因为它错过了刚才生产者的notify。

 

public class WhyNotifySynchronized {
    static Object oj = new Object();
    static ArrayList<String> list = new ArrayList<>();
    public static void main(String[] args) {
        /*
        * wait()和notify()没有使用同步代码块的情况\
        */
        new Thread(){            //消费者线程,集合中有字符串则拿走,没有则主动wait
            public void run(){
                try {
                    take();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();

        new Thread(){        //生产者线程,负责往集合添加内容,并叫醒消费者
            public void run(){
                produce();
            }

        }.start();
    }

    private static void  take() throws InterruptedException {
        while (list.size() == 0) {        //重复等待直到集合有内容再拿走、输出
            oj.wait();
        }
        System.out.println(list.remove(0));
    }

    private static void produce(){        //负责生产,叫醒消费者
        list.add("name");
        oj.notify();
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值