wait-notify的另一种情况

wait-notify用在经典的生产者-消费者模型。一般代码都是先初始化consumer,然后再初始化producer,程序正常运行。这是带有wait()先进入同步语句块,带有notifyAll()的后进入同步语句块。现在反过来带有notifyAll()先进入同步语句块,儿带有wait()的后进入语句块,这时候程序会一直阻塞,觉得很蹊跷,带着这个对synchronized,wait,notify又深入研究了一番。有一些结论和大家分享一下,首先来看synchronized,这个大家都很清楚,相当于排他锁谁先持有,其他线程必须得等待直到释放。依据这样的结论,
场景一 两个线程同时执行synchronized语句块,肯定只有一个线程成功,而另外一个阻塞。
下面的代码验证了结论:
            synchronized (lock) {
//                    for(int i = 0; i < 1000000;i++);
//                lock.notify();
                try {
                    Thread.sleep(50000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "notify other!");
            }
Thread-1被synchronized阻塞,Thread-0进入语句块执行sleep方法


 
当Thread-0执行完毕释放锁,Thread-1开始执行。此时Thread-0消亡


 
 
场景二 两个synchronized块中执行wait()的线程,会先后进入语句块,而不是其中一个等待另外一个执行完毕以后再进入。为什么会这样呢?我又重新看了一下jdk的comment发现,The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread
 notifies threads waiting on this object's monitor to wake up。wait首先释放同步语句块的锁,再执行wait,此时其他线程就能进入了。
  synchronized (lock) {
//                    for(int i = 0; i < 1000000;i++);
//                lock.notify();
                try {
                    Thread.sleep(50000);
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "notify other!");
            }


 
场景三,回到开始描述的场景,首先notify的线程先进入,wait的后进入。就会导致看似notify不生效。


 


 
看第二张堆栈图,一切就都明白了,注意看waiting on 和waiting to。 synchronized和wait()虽然是监控的同一对象,但不是一回事儿。 synchronized只有其他线程释放了锁,其他线程才能获得锁,而wait只能由notify唤醒。还原一下整个过程,notify先进入同步语句块,这时wait的wait to lock等待进入。
后来再到执行notify的时候其实是没用的,wait还被阻塞在 synchronized之外。再后来退出同步块,带有 wait的语句块进入执行wait操作,就一直waiting on了,此时貌似notify没起到作用。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值