-
这个java程序,为什么一个notify唤醒了3个wait0
//主程序
class Demo6
{
public static void main(String[] args)
{
Go1 q=new Go1();
Go2 qq=new Go2(q);
Go3 qqq=new Go3(q);
Come w=new Come(q);
q.start();
qq.start();
qqq.start();
w.start();
}
}
//线程1,打印1,等待,唤醒后打印一
class Go1 extends Thread
{
public void run()
{
synchronized (this)
{
System.out.println("1");
try
{
wait();
}
catch (Exception e)
{
}
}
System.out.println("一");
}
}
//线程2,打印2,等待,唤醒后打印二
class Go2 extends Thread
{
Go1 g;
Go2(Go1 g)
{
this.g=g;
}
public void run()
{
synchronized (g)
{
System.out.println("2");
try
{
g.wait();
}
catch (Exception e)
{
}
}
System.out.println("二");
}
}
//线程3,打印3,等待,唤醒后打印三
class Go3 extends Thread
{
Go1 g;
Go3(Go1 g)
{
this.g=g;
}
public void run()
{
synchronized (g)
{
System.out.println("3");
try
{
g.wait();
}
catch (Exception e)
{
}
}
System.out.println("三");
}
}
//唤醒线程
class Come extends Thread
{
Go1 r;
Come(Go1 r)
{
this.r=r;
}
public void run()
{
try
{
sleep(100);
}
catch (Exception e)
{
}
synchronized (r)
{
r.notify();
System.out.println("lock open");
}
}
}
2012年10月22日 21:36
5个答案 按时间排序 按投票排序
-
synchronized (g) 锁定的都是同一个Go1,r.notify();会解除synchronized (g) 和synchronized (this)的锁,当然有三个线程被唤醒了,如果每个线程都是不同Go1实例,就不会了。
2012年10月24日 22:10
-
如果一个线程对象最为锁对象,当线程执行完成后,会 notifyAll(); 其他线程.
原因:
Thread.exit() 方法
/** * This method is called by the system to give a Thread * a chance to clean up before it actually exits. */ private void exit() { if (group != null) { group.remove(this); group = null; } // ... }
其中的 group.remove(this);
/** * Removes the specified Thread from this group. * @param t the Thread to be removed * @return if the Thread has already been destroyed. */ void remove(Thread t) { synchronized (this) { //... if (nthreads == 0) { notifyAll(); } // ... } }
以上结论均为目测,无官方文档证实~~~~~~~
测试代码:public class Test { public static Lock lock = new Lock(); public static void main(String[] args) { A a = new A(); B b = new B(); a.start(); b.start(); try { TimeUnit.SECONDS.sleep(3); } catch(InterruptedException e) { e.printStackTrace(); } synchronized(lock) { try { System.out.println("catch lock"); lock.start(); System.out.println("notifyall"); } catch(Exception e) { e.printStackTrace(); } } } static class A extends Thread { @Override public void run() { synchronized(lock) { System.out.println("a"); try { lock.wait(); } catch(InterruptedException e) { e.printStackTrace(); } System.out.println("aa"); } } } static class B extends Thread { @Override public void run() { synchronized(lock) { System.out.println("b"); try { lock.wait(); } catch(InterruptedException e) { e.printStackTrace(); } System.out.println("bb"); } } } static class Lock extends Thread { } }
2012年10月23日 12:19
-
原因是共用的对象本身也是一个线程,所以notify的时候,如果被唤醒的是Go1的线程,那么Go2和Go3中的g.wait();也会跟着返回,所以相当于Go1,Go2,Go3都被唤醒,然后一起争夺锁。把共用的对象换成一个普通的对象就没有问题了。代码如下:
class Demo6 { public static void main(String[] args) { Go g = new Go(); Go1 q=new Go1(g); Go2 qq=new Go2(g); Go3 qqq=new Go3(g); Come w=new Come(g); q.start(); qq.start(); qqq.start(); w.start(); } } class Go{ } class Go1 extends Thread { Go g; Go1(Go g) { this.g=g; } public void run() { synchronized (g) { System.out.println("1"); try { g.wait(); } catch (Exception e) { } } System.out.println("一"); } } class Go2 extends Thread { Go g; Go2(Go g) { this.g=g; } public void run() { synchronized (g) { System.out.println("2"); try { g.wait(); } catch (Exception e) { } } System.out.println("二"); } } class Go3 extends Thread { Go g; Go3(Go g) { this.g=g; } public void run() { synchronized (g) { System.out.println("3"); try { g.wait(); } catch (Exception e) { } } System.out.println("三"); } } class Come extends Thread { Go r; Come(Go r) { this.r=r; } public void run() { try { sleep(100); } catch (Exception e) { } synchronized (r) { r.notify(); System.out.println("lock open"); } } }
2012年10月23日 11:21
-
测试了一下,情况应该是:
有时只唤醒一个,而只有在Go1 q先被唤醒的情况下,其他的才会被唤醒;
如果把同步的对象设为全局变量应该就会只唤醒一个。
怀疑是不是和对象的引用或者虚假唤醒有关系。引用在没有被通知、中断或超时的情况下,线程还可以唤醒一个所谓的虚假唤醒 (spurious wakeup)。虽然这种情况在实践中很少发生,但是应用程序必须通过以下方式防止其发生,即对应该导致该线程被提醒的条件进行测试,如果不满足该条件,则继续等待。
2012年10月23日 10:05
相关推荐
在学习Java过程中,自己收集了很多的Java的学习资料,分享给大家,有需要的欢迎下载,希望对大家有用,一起学习,一起进步。
主要介绍了Java wait和notify虚假唤醒,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
在实现中,assertion就是在程序中的一条语句,它对一个boolean表达式进行检查,一个正确程序必须保证这个boolean表达式的值为true;如果该值为false,说明程序已经处于不正确的状态下,系统将给出警告或退出。...
60、java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用? 答:有两种实现方法,分别是继承Thread类与实现Runnable接口 用synchronized关键字修饰同步方法 反对使用...
主要介绍了Java多线程基础 线程的等待与唤醒,需要的朋友可以参考下
update() 在线程同步中,为了唤醒另一个等待的线程,使用下列方法 () [单选题] * A.sleep() B.wait() C.notify()(正确答案) D. join() Java高级程序设计测试含答案全文共40页,当前为第4页。Java提供以下哪个...
生产者和消费者是一个十分经典的多线程协作模式 **常见方法:** - void wait() 当前线程等待,直到被其他线程唤醒 - void notify() 随机唤醒单个线程 - void notifyAll() 唤醒所有线程
当JAVA程序违反了JAVA的语义规则时,JAVA虚拟机就会将发生的错误表示为一个异常。违反语义规则包括2种情况。一种是JAVA类库内置的语义检查。例如数组下标越界,会引发IndexOutOfBoundsException;访问null的对象时会...
创建一个老板线程(生产者):花了5秒做包子,做好包子之后,调用notify方法,唤醒顾客吃包子 注意: 顾客和老板线程必须使用同步代码块包裹起来,保证等待和唤醒只能有一个在执行 同步使用的锁对象必须保证唯一 只有锁...
在实现中,assertion就是在程序中的一条语句,它对一个boolean表达式进行检查,一个正确程序必须保证这个boolean表达式的值为true;如果该值为false,说明程序已经处于不正确的状态下,系统将给出警告或退出。...
唤醒在此对象监视器上等待的单个线程,如果所有线程都在此对象上等待,则会任意选择唤醒其中一个线程。 public final void wait() 当前线程必须拥有此对象监视器。该线程发布对此监视器的所有权并等待,...
在Object.java中,定义了wait(), notify()和notifyAll()等接口。wait()的作用是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的锁。下面通过本文给大家介绍Java中线程的等待与唤醒知识,感兴趣的...
一个condition对象的signal(signalAll)方法和该对象的await方法是一一对应的,也就是一个condition对象的signal(signalAll)方法不能唤醒其他condition对象的await方法 ReentrantLock类可以唤醒指定条件的...
使用Condition重写waitnotify案例并实现一个有界队列.mp4 深入解析Condition源码.mp4 实战:简易数据连接池.mp4 线程之间通信之join应用与实现原理剖析.mp4 ThreadLocal 使用及实现原理.mp4 并发工具类...
notify():执行该方法的线程唤醒在等待池中等待的任意一个线程,把线程转到锁池中等待(注意锁池和等待池的区别) notifyAll():执行该方法的线程唤醒在等待池中等待的所有线程,把线程转到锁池中等待。 注意:上述...
第32节使用Condition重写wait/notify案例并实现一个有界队列00:22:05分钟 | 第33节深入解析Condition源码00:21:15分钟 | 第34节实战:简易数据连接池00:24:53分钟 | 第35节线程之间通信之join应用与实现原理剖析...
第32节使用Condition重写wait/notify案例并实现一个有界队列00:22:05分钟 | 第33节深入解析Condition源码00:21:15分钟 | 第34节实战:简易数据连接池00:24:53分钟 | 第35节线程之间通信之join应用与实现原理剖析...
第32节使用Condition重写wait/notify案例并实现一个有界队列00:22:05分钟 | 第33节深入解析Condition源码00:21:15分钟 | 第34节实战:简易数据连接池00:24:53分钟 | 第35节线程之间通信之join应用与实现原理剖析...
第32节使用Condition重写wait/notify案例并实现一个有界队列00:22:05分钟 | 第33节深入解析Condition源码00:21:15分钟 | 第34节实战:简易数据连接池00:24:53分钟 | 第35节线程之间通信之join应用与实现原理剖析...