关于wait和notify的一些疑问

dreamhunter_lan 2011-08-30 11:32:43
1、notify与notifyAll的具体区别是啥?notify是随机选择一个线程来唤醒它,其他的还是处于WAITING状态,notifyAll()唤醒所有等待该对象监视锁的线程,让它们去竞争该对象的锁。对于这两种方式,最终都是一个线程获得监视锁,但是具体实现上有什么不同呢?有什么情况是用notify优于使用notifyAll的?

2、所谓的spurious wakeup是指什么?有没有例子说明一下?

3、这点是关于一个由于调用对象的wait方法进入WAITING状态的线程,最后被唤醒又再可以被CPU调度时(不管是因为什么变为可以被CPU调度的)所发生的事:这个线程被从wait set中移除,又去和其他线程抢夺监视锁,获得锁后恢复现场(不知道这里说恢复现场对不对?)我想知道所谓获得锁是什么意思?就是获得了一块内存吗?

4、wait函数是什么时候返回的?是调用wait后马上返回还是再这个线程再次获得监视锁后返回,然后又对while的条件进行检测(我觉得是后者)

5、notify和notifyAll也会释放锁吧?会不会有那种场景:那个调用notify(或notifyAll)后,紧接着这个语句后面还执行其他语句?比如:notify(); other_statement;
...全文
172 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
阳明 to life 2011-08-31
  • 打赏
  • 举报
回复
1.假如三个线程A、B、C,
synchronized(obj)
{
obj.wait();//某种情况A不执行wait
xxxx//处理之后,导致A能够notify,B和C不能
}
然后可能某时B C都wait后,A进入,A如果只notify一个,你会发现B醒了继续执行结束,但是C一直wait没法醒
此时用notifyAll就会让B和C等在资源上而不是wait等人唤醒
2.不清楚
3.锁就相当于资源,比如上面的obj那个,假如就一把锁,你获得了锁,把仓库(块)锁上了进入了仓库(块执行),别人此时没锁的钥匙就没法进入,你出仓库把锁给别人,别人再锁上等等
4.notify和notifyAll才能让wait返回
5.notify和notifyAll只会唤醒在wait的线程,不会释放锁
小笨熊 2011-08-31
  • 打赏
  • 举报
回复
收藏学习下,很详细
qybao 2011-08-31
  • 打赏
  • 举报
回复
1
把synchronized比作一扇门,把wait队列比作一个休息室,那么notify就是在休息室随机通知某个人,把门钥匙给他(看谁顺眼给谁),其他人继续在休息室等待。而notifyAll就是通知所有人,然后把钥匙抛出去,让所有人抢,此时,休息室的人就不会再安分地呆在休息室等待了,而是会挤在门前等待强钥匙。
所以区别就是,nofity的时候,其他人还在等待室,notifyAll的时候,其他人挤在门前

2
spurious wakeup就是虚假唤醒,比如1中,notifyAll的时候,所有人都挤在门前了,但是有些人是不符合条件的,应该继续等待,所以就算他们挤在门前了,也要管理员检查一下他们的身份,不符合的继续赶到休息室里去。这样的唤醒就是虚假的唤醒。在程序中,一般用while循环来做
while(condition) {
wait(); //即使线程被唤醒了,执行while检查,发现还是满足等待条件,就让线程继续等待
}

3
线程进入等待队列的时候,线程的进入等待队列前的信息都被压栈,所谓的恢复现场,就是线程信息出栈,让线程恢复进入等待前的状态。获得锁就是获得对象的控制权限,系统有个对象的monitor,要想控制对象,就要从monitor中获得权限,比如你要进一个门,就要找管理员拿钥匙。从内存的角度来说,可以理解为获得一块内存的访问权,从实现的角度来说,也许只是在monitor设置一个flag(就看底层怎么实现锁管理),就好像在管理处登个记。

4
你所说的返回是什么意思?如果说是wait方法本身的返回,那么程序会在wait处发生等待,直到notify或notifyAll以后才返回继续执行后面的代码。如果说是程序的返回,那么就是把线程当前的状态压栈,然后把线程放到等待队列,然后程序指针就转到其他地方去执行了(因为CPU放弃让线程继续使用)。

5
notify和notifyAll只是唤醒其他等待中的线程,释放不释放锁,就要看代码是否退出synchronized块,也就是说某个人上厕所,他喊一声拉完了,这样其他等待的人就知道了,但是那个人还没离开厕所,还在占用着,其他人也只能在门口等待,直道那个人离开厕所,即离开synchronized块


xiao_cs 2011-08-31
  • 打赏
  • 举报
回复
赞个

[Quote=引用 8 楼 qybao 的回复:]
1
把synchronized比作一扇门,把wait队列比作一个休息室,那么notify就是在休息室随机通知某个人,把门钥匙给他(看谁顺眼给谁),其他人继续在休息室等待。而notifyAll就是通知所有人,然后把钥匙抛出去,让所有人抢,此时,休息室的人就不会再安分地呆在休息室等待了,而是会挤在门前等待强钥匙。
所以区别就是,nofity的时候,其他人还在等待室,notifyAll的时候,其他人……
[/Quote]
阳明 to life 2011-08-31
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 zhao251021539 的回复:]

第二哥问题我也想知道,百度了一下 无奈此人 错别字太多,我意淫能力不够啊。

http://blog.csdn.net/turkeyzhou/article/details/5775301
[/Quote]
昨天我倒是谷歌搜到了。。。但是不知道是不是正确的
http://tieba.baidu.com/f?kz=702270551
你如果不是想进百度。。其实可以不用百度搜技术的东西
perfe_ct 2011-08-31
  • 打赏
  • 举报
回复
mark一下 学习了
meran 2011-08-31
  • 打赏
  • 举报
回复
第二哥问题我也想知道,百度了一下 无奈此人 错别字太多,我意淫能力不够啊。

http://blog.csdn.net/turkeyzhou/article/details/5775301
24K純帥 2011-08-31
  • 打赏
  • 举报
回复
喔,学习了~
softroad 2011-08-31
  • 打赏
  • 举报
回复
学习了。。
lequery 2011-08-31
  • 打赏
  • 举报
回复
学习 。。。
安心逍遥 2011-08-31
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 zhouyuqwert 的回复:]
1.假如三个线程A、B、C,
synchronized(obj)
{
obj.wait();//某种情况A不执行wait
xxxx//处理之后,导致A能够notify,B和C不能
}
然后可能某时B C都wait后,A进入,A如果只notify一个,你会发现B醒了继续执行结束,但是C一直wait没法醒
此时用notifyAll就会让B和C等在资源上而不是wait等人唤醒
2……
[/Quote]

+1

学习了
client_user 2011-08-31
  • 打赏
  • 举报
回复
路过,提点建议:
操作系统知识借来理解哈
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 qybao 的回复:]
1
把synchronized比作一扇门,把wait队列比作一个休息室,那么notify就是在休息室随机通知某个人,把门钥匙给他(看谁顺眼给谁),其他人继续在休息室等待。而notifyAll就是通知所有人,然后把钥匙抛出去,让所有人抢,此时,休息室的人就不会再安分地呆在休息室等待了,而是会挤在门前等待强钥匙。
所以区别就是,nofity的时候,其他人还在等待室,notifyAll的时候,其他人……
[/Quote]

最后那段太搞笑了
  • 打赏
  • 举报
回复
人才呀、
学习了
qybao 2011-08-31
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 dreamhunter_lan 的回复:]
谢谢阿宝~~~在第一问那里,一般都建议用notifyAll唤醒所有在该对象wait set中的线程,让它们自己去抢,有没有什么情况下是用notify会比较好的?
[/Quote]
这个就看具体需求了,用多个锁的例子一般采用notify比较好。
比如A线程组执行任务1,B线程组执行任务2,任务2依赖任务1,那么A线程组做好任务1准备条件后,只需要唤醒B线程组中任意一个线程就可以了,这时候可以不用把B线程组全部唤醒。不过这样的处理需要协调好,否则没有被notify的线程就会一直wait,导致程序可能停止而无法结束,所以一般在结束条件处都会notifyAll来唤醒所有的线程。
dreamhunter_lan 2011-08-31
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 qybao 的回复:]

1
把synchronized比作一扇门,把wait队列比作一个休息室,那么notify就是在休息室随机通知某个人,把门钥匙给他(看谁顺眼给谁),其他人继续在休息室等待。而notifyAll就是通知所有人,然后把钥匙抛出去,让所有人抢,此时,休息室的人就不会再安分地呆在休息室等待了,而是会挤在门前等待强钥匙。
所以区别就是,nofity的时候,其他人还在等待室,notifyAll的时候,其他……
[/Quote]
谢谢阿宝~~~在第一问那里,一般都建议用notifyAll唤醒所有在该对象wait set中的线程,让它们自己去抢,有没有什么情况下是用notify会比较好的?

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧