黑马程序员技术交流社区
标题:
等待唤醒机制的小迷惑
[打印本页]
作者:
yhnan
时间:
2013-4-6 11:24
标题:
等待唤醒机制的小迷惑
本帖最后由 易贺男 于 2013-4-6 18:40 编辑
class Sisuo
{
public static void main(String[] args)
{
Person p = new Person();
Input in = new Input(p);
Output out = new Output(p);
Thread t = new Thread(in);
Thread t1 = new Thread(out);
t.start();
t1.start();
}
}
//两个线程一个输入一个输出
class Person
{
String name;
String sex;
boolean flang = false;
}
class Input implements Runnable
{
private Person n;
Input(Person n)
{
this.n = n;
}
public void run()
{
int x = 0 ;
while(true)
{
synchronized(n)
{
if(n.flang)
try{n.wait();}catch(Exception e){}//wait,notify.为什么是放在同步的里边?
if(x==0)
{
n.name="zhangsan";
n.sex="nan";
}
else
{
n.name="拉拉";
n.sex="女";
}
x=(x+1)%2;
n.flang=true;
n.notify();
}
}
}
}
class Output implements Runnable
{
private Person n;
Output(Person n)
{
this.n = n;
}
public void run()
{
while(true)
{
synchronized(n)
{
if(!n.flang)
try{n.wait();}catch(Exception e){}//.......?
System.out.println(n.name+"...."+n.sex);
n.flang=false;
n.notify();
}
}
}
}
复制代码
为什么wait和notify是放在同步里边的?我的理解是:因为input和output用的是同一个锁,如果放在里边那么负责input的线程等待之后,只释放了执行权,没有放锁,那之后Output的线程岂不是进不来。可是通过代码的运行已经证明我的理解是错误的,但我还是转不过来。求各位指点
作者:
Lobster
时间:
2013-4-6 12:22
{:soso_e199:}wait和notify是针对同步锁的等待唤醒操作,所以放在同步块中才有意义,另外,你的理解是错的,wait方法调用不止释放了执行权同时也释放了锁,因此持有同一个所的线程在其他线程wait之后是能够进来的。
作者:
张洪慊
时间:
2013-4-6 12:23
我帮你找的比较规范点说法:
为什么要使用线程通信?
1.当使用synchronized 来修饰某个共享资源时(分同步代码块和同步方法两种情况),当某个线程获得共享资源的锁后就可以执行相应的代码段,直到该线程运行完该代码段后才释放对该共享资源的锁,让其他线程有机会执行对该共享资源的修改。
2.当某个线程占有某个共享资源的锁 时,如果另外一个线程也想获得这把锁运行就需要使用wait() 和notify()/notifyAll()方法来进行线程通讯了。
结合上面两句话举个例子:就是你上面的例子,如果不用wait,notify的话,只能按第一条说的来执行,这样就很可能出现cpu在一直执行该线程,不切换到另一个线程。(一直执行输出,zhangsan,nan一堆,拉拉,女一堆)如果我想控制让两者交替输出呢?
也就是赋一次值,输出一次。这时候用到第二条。
关于wait(JDK):
前提:当前线程必须拥有此 对象监视器(锁)。
该线程发布(放弃)对此监视器(锁)的所有权并等待,直到其他线程通过调用 notify 方法,
或 notifyAll 方法通知 在此对象的监视器上等待 的线程醒来.
然后该线程将等到 重新获得对监视器的所有权后 才能继续执行。
作者:
陈丽莉
时间:
2013-4-6 18:23
若还有问题,请继续追问; 没有的话,将帖子分类改成【已解决】~
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2