wait() 一定需要notify()唤醒吗?
来源:互联网 发布:anjular.js 编辑:程序博客网 时间:2024/04/30 20:50
wait() 一定需要notify()唤醒吗?
20120810
写这篇文章是源于论坛里的一个帖子, "线程同步问题,分析下程序运行结果" 其地址为:
http://topic.csdn.net/u/20120808/17/f1742060-7501-430b-b509-a492eef535f5.html.
当时按照一般的wait(),notify()思想做了解释,但楼主质疑,认为解释的与实际情况不一致,再后来测试时,也确实发现楼主的质疑是对的。 虽然楼主已经结贴了,但我觉得还是应该弄清楚,为什么会有这样两种结果。
先来看一下帖子的代码:
package test;public class ThreadA{public static void main(String[] args){ThreadB b = new ThreadB();Threadc c = new Threadc();c.setName("c线程");b.setName("b线程");c.start();System.out.println(Thread.currentThread().getName()+"is start....");synchronized(c){try{System.out.println("waiting for b1 to complete....");c.wait();System.out.println("Completed.now back to"+Thread.currentThread().getName());b.start();}catch(InterruptedException e){}}}}class ThreadB extends Thread{int total;public void run(){synchronized(this){System.out.println(Thread.currentThread().getName()+"is running..");for(int i=0;i<10;i++){total +=i;}System.out.println("total is"+total);}}}class Threadc extends Thread{int sum=1;public void run(){synchronized(this){System.out.println(Thread.currentThread().getName()+"is running..");for(int i=1;i<10;i++){sum *=i;}System.out.println("sum is"+sum);notify();}}}
代码运行的结果有2种:
1 程序完全运行完,正常退出。
main is start....
c线程 is running..
sum is 362880
waiting for b1 to complete....
Completed.now back tomain
b线程 is running..
total is 45
2 程序停在那“不动”了,不能正常退出。
main is start....
c线程 is running..
sum is 362880
waiting for b1 to complete....
当时我的解释:
“这两种结果产生的原因是以对象c为同步对象的两段代码块,谁先运行的问题。
第一种情况,主线程优先运行到synchonized(c)标记的同步代码块,这时c线程synchronized(this)标记的代码块就暂时无法运行。主线程运行到c.wait()时,主线程释放同步对象的锁,进入阻塞状态,c线程会由阻塞状态变为运行状态。c线程运行完后,通过其 notify(),使主线程由阻塞状态进入运行状态,正常执行完毕。
第二种情况,c线程优先运行到synchronized(this)标记的代码块,这时主线程因为得不到同步对象锁而阻塞。当c线程运行结束后,释放同步对象锁,这时主线程由阻塞进入运行状态,当运行到c.wait()时,进入阻塞状态,因没有程序运行notify(),所以一直阻塞下去了。
”
当经楼主质疑后,经过大量测试,发现上面的解释是不正确的。正象楼主质疑的一样,测试发现每次程序运行都是c线程先进入同步代码段,而主线程的同步代码段是在c线程退出同步代码段后进入的。
关键问题就在这了: 既然每次都是c线程进入同步代码段,那主线程的c.wait()将一直停在那等才对呢,根本就不能有第一种情况出现!因为c线程的notify()已经运行完了!没有谁再会唤醒这个wait了。
但问题是有时(而且根据测试是多数时候)程序继续运行,而且正常退出了。
真是不可思议,与自己以前看到的,学到的知识发生冲突了!
为了进一步证实,程序的wait可以不需要 noyify()唤醒,我干脆在Threadc类里,把notify()注释掉了,编译运行(都是多次运行),发现结果和原来一样:有时正常退出,有时停那不动。
问题又来了,既然不需要唤醒,那应该是每次都能正常退出啊?为什么有时停那了呢?
继续测试,在主线程的同步代码段里,在c.wait()前加一句:
System.out.println("线程c的状态是:"+c.isAlive());
编译运行后,发现所有正常结束的时候,上述语句输出的都是 true. 而不能正常结束的时候,输出的都是false!
因此说明线程正常结束后,会使以这个线程对象运行的wait()等待,退出等待状态!而如果在运行wait()之前,线程已经结束了,则这个wait就没有程序唤醒了。
看看thread类的原码,证明了我上述观点!
原码里的join()方法,实际上就是运行的 wait(). 需要运行join的线程运行join方法,实际上是在此线程上调用了需要加入的线程对象的wait()方法,加入的线程运行完后,自然从wait退出了。
1 线程对象的wait()方法运行后,可以不用其notify()方法退出,会在线程结束后,自动退出。
2 线程间的等待唤醒机制,最好不要用线程对象做同步锁!
- wait() 一定需要notify()唤醒吗?
- wait() 不一定需要notify()唤醒
- wait不一定需要notify
- java 中wait和notify 线程等待和线程唤醒的使用方式 需要借助synchronized
- 多线程wait等待和notify唤醒
- JAVA 线程等待唤醒,wait and notify
- java多线程notify()无法唤醒wait()问题
- Java-线程$等待唤醒机制(wait,notify)
- Java线程之等待wait唤醒notify示例(一)
- java多线程学习之线程通信-wait()等待 notify()唤醒
- wait & notify
- wait()/notify()
- Wait/Notify
- wait notify
- 使用wait、notify、notifyAll需要注意的地方
- 线程间通信 等待唤醒机制 wait notify notifyAll lock Condition唤醒 停止线程interrupt 守护线程setDaemon join yield
- Java多线程--同步与死锁:synchronized;等待与唤醒:wait、notify、notifyAll;生命周期
- java多线程-线程间通信-示例代码-解决安全问题-等待唤醒机制wait()notify()notifyAll()
- 打开程序会弹出一个用户账户控制询问窗口的原理
- 使用NetFlow分析网络异常流量(6)
- 数据库设计浅谈
- DCOM在windows 2008 Server的配置
- 程序员给自己五年前的10个建议
- wait() 一定需要notify()唤醒吗?
- C语言的三种整型数据类型:int、short int和long int
- Linux静态链接(库)、动态链接(库)、可执行文件加载相关问题
- globalmem.c:193:2: 错误:隐式声明函数‘kmalloc’ [-Werror=implicit-function-declaration]
- 日记2012-8-9
- Android ApiDemo学习(四)Views—— 4 Expandable Lists、Focus、Gallery
- 镁天三国育将篇
- 错误: 初始值设定项里有未知的字段‘ioctl’
- php_network_getaddresses: getaddrinfo failed