`
uule
  • 浏览: 6310728 次
  • 性别: Icon_minigender_1
  • 来自: 一片神奇的土地
社区版块
存档分类
最新评论

这个java程序,为什么一个notify唤醒了3个wait

 
阅读更多

1、

public 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");
		}
	}
}

结果:

1
2
3
lock open


 

答案:

原因是共用的对象本身也是一个线程,所以notify的时候,如果被唤醒的是Go1的线程,那么Go2和Go3中的g.wait();也会跟着返回,所以相当于Go1,Go2,Go3都被唤醒,然后一起争夺锁。把共用的对象换成一个普通的对象就没有问题了。代码如下:

public class Demo7 {
	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");
		}
	}
}

 结果:

1
2
3
lock open

 

来源:javaeye问答

http://www.iteye.com/problems/89570

 

分享到:
评论

相关推荐

    41.线程间的通信-wait与notify-只唤醒一个线程或所有线程.mp4

    在学习Java过程中,自己收集了很多的Java的学习资料,分享给大家,有需要的欢迎下载,希望对大家有用,一起学习,一起进步。

    Java wait和notify虚假唤醒原理

    主要介绍了Java wait和notify虚假唤醒,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    java 面试题 总结

    在实现中,assertion就是在程序中的一条语句,它对一个boolean表达式进行检查,一个正确程序必须保证这个boolean表达式的值为true;如果该值为false,说明程序已经处于不正确的状态下,系统将给出警告或退出。...

    java笔试题大集合及答案(另附各大公司笔试题)

    60、java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用? 答:有两种实现方法,分别是继承Thread类与实现Runnable接口 用synchronized关键字修饰同步方法 反对使用...

    Java多线程基础 线程的等待与唤醒(wait、notify、notifyAll)

    主要介绍了Java多线程基础 线程的等待与唤醒,需要的朋友可以参考下

    Java高级程序设计测试含答案.docx

    update() 在线程同步中,为了唤醒另一个等待的线程,使用下列方法 () [单选题] * A.sleep() B.wait() C.notify()(正确答案) D. join() Java高级程序设计测试含答案全文共40页,当前为第4页。Java提供以下哪个...

    Java多线程的等待唤醒机制代码演示通俗易懂

    生产者和消费者是一个十分经典的多线程协作模式 **常见方法:** - void wait() 当前线程等待,直到被其他线程唤醒 - void notify() 随机唤醒单个线程 - void notifyAll() 唤醒所有线程

    JAVA面试题集合面试技能大全

    当JAVA程序违反了JAVA的语义规则时,JAVA虚拟机就会将发生的错误表示为一个异常。违反语义规则包括2种情况。一种是JAVA类库内置的语义检查。例如数组下标越界,会引发IndexOutOfBoundsException;访问null的对象时会...

    Java-线程状态和等待唤醒机制和线程池

    创建一个老板线程(生产者):花了5秒做包子,做好包子之后,调用notify方法,唤醒顾客吃包子 注意: 顾客和老板线程必须使用同步代码块包裹起来,保证等待和唤醒只能有一个在执行 同步使用的锁对象必须保证唯一 只有锁...

    超级有影响力霸气的Java面试题大全文档

    在实现中,assertion就是在程序中的一条语句,它对一个boolean表达式进行检查,一个正确程序必须保证这个boolean表达式的值为true;如果该值为false,说明程序已经处于不正确的状态下,系统将给出警告或退出。...

    java多线程通信之等待唤醒机制

     唤醒在此对象监视器上等待的单个线程,如果所有线程都在此对象上等待,则会任意选择唤醒其中一个线程。  public final void wait()  当前线程必须拥有此对象监视器。该线程发布对此监视器的所有权并等待,...

    Java中线程的等待与唤醒_动力节点Java学院整理

    在Object.java中,定义了wait(), notify()和notifyAll()等接口。wait()的作用是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的锁。下面通过本文给大家介绍Java中线程的等待与唤醒知识,感兴趣的...

    java多线程系列(四)ReentrantLock的使用.docx

    一个condition对象的signal(signalAll)方法和该对象的await方法是一一对应的,也就是一个condition对象的signal(signalAll)方法不能唤醒其他condition对象的await方法 ReentrantLock类可以唤醒指定条件的...

    Java并发编程原理与实战

    使用Condition重写waitnotify案例并实现一个有界队列.mp4 深入解析Condition源码.mp4 实战:简易数据连接池.mp4 线程之间通信之join应用与实现原理剖析.mp4 ThreadLocal 使用及实现原理.mp4 并发工具类...

    锁、生产者与消费者.pdf

    notify():执行该方法的线程唤醒在等待池中等待的任意一个线程,把线程转到锁池中等待(注意锁池和等待池的区别) notifyAll():执行该方法的线程唤醒在等待池中等待的所有线程,把线程转到锁池中等待。 注意:上述...

    龙果java并发编程完整视频

    第32节使用Condition重写wait/notify案例并实现一个有界队列00:22:05分钟 | 第33节深入解析Condition源码00:21:15分钟 | 第34节实战:简易数据连接池00:24:53分钟 | 第35节线程之间通信之join应用与实现原理剖析...

    java并发编程

    第32节使用Condition重写wait/notify案例并实现一个有界队列00:22:05分钟 | 第33节深入解析Condition源码00:21:15分钟 | 第34节实战:简易数据连接池00:24:53分钟 | 第35节线程之间通信之join应用与实现原理剖析...

    龙果 java并发编程原理实战

    第32节使用Condition重写wait/notify案例并实现一个有界队列00:22:05分钟 | 第33节深入解析Condition源码00:21:15分钟 | 第34节实战:简易数据连接池00:24:53分钟 | 第35节线程之间通信之join应用与实现原理剖析...

    Java 并发编程原理与实战视频

    第32节使用Condition重写wait/notify案例并实现一个有界队列00:22:05分钟 | 第33节深入解析Condition源码00:21:15分钟 | 第34节实战:简易数据连接池00:24:53分钟 | 第35节线程之间通信之join应用与实现原理剖析...

Global site tag (gtag.js) - Google Analytics