博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
wait-notify的另一种情况
阅读量:4214 次
发布时间:2019-05-26

本文共 1579 字,大约阅读时间需要 5 分钟。

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没起到作用。

转载地址:http://pqdmi.baihongyu.com/

你可能感兴趣的文章
cocos2dx-2.x CCFileUtils文件管理类分析(4)
查看>>
CCNode 的onEnter函数何时调用分析
查看>>
cocos2dx基础篇(24)——基本动画CCAnimation/CCAnimate
查看>>
android使用ClippingNode-修改opengl设置
查看>>
Windows7 64位系统搭建Cocos2d-x 2.2.1最新版以及Android交叉编译环境(详细教程)
查看>>
android 如何进行 代码混淆
查看>>
android 数字签名使用 -- 参考网站
查看>>
lua 模块思考(1)
查看>>
如何修改Eclipse的 workspace目录
查看>>
.pvr.ccz 与 png 格式 互转的解决方案
查看>>
将Texture Packer制作的.pvr.ccz和.plist文件还原为多个原图
查看>>
将Texture Packer制作的.pvr.ccz和.plist文件还原为多个原图--格式之后
查看>>
PIL The _imaging C module is not installed
查看>>
将Texture Packer制作的.pvr.ccz和.plist文件还原为多个原图 -- 使用说明文档
查看>>
将Texture Packer制作的.pvr.ccz和.plist文件还原为多个原图 -- 可以一下转化多个
查看>>
查看Eclipse版本
查看>>
[cocos2d-x] --- 使用位图工具自定义字体
查看>>
BMFont中文字体图集制作的方法~(for unity ngui)
查看>>
cocos2dx添加文本的三种方法及适用情况CCLabelTTF,CCLabelBMFont,CCLabelAtlas
查看>>
libgdx下Texture packer工具使用
查看>>