`
uule
  • 浏览: 6337505 次
  • 性别: 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

 

分享到:
评论

相关推荐

    Java 同步方式 wait和notify/notifyall

    2. **notify()**:这个方法会唤醒在当前对象监视器上等待的一个线程。如果有多个线程在等待,系统会随机选择其中一个线程进行唤醒。被唤醒的线程并不会立即执行,而是要等到当前线程释放锁之后,才能进入临界区。 3...

    java之wait,notify的用法([ 详解+实例 ])

    wait方法是Object类的一个方法,用于让当前线程进入等待状态,直到其他线程调用notify或notifyAll方法来唤醒它。在wait方法中,当前线程会释放它所占有的锁,并进入等待状态。wait方法可以带有参数,指定等待的时间...

    java中几个notify、wait使用实例

    当一个线程调用`notify()`方法时,它会选择在等待队列中任意一个处于等待状态的线程进行唤醒,但并不释放锁,这意味着被唤醒的线程需要在下次获取锁时竞争。由于`notify()`只能唤醒一个线程,所以有时可能需要多次...

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

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

    wait_notify_demo

    1. `wait()`: 当一个线程调用某个对象的`wait()`方法时,它会释放该对象的锁,并进入等待状态,直到其他线程调用了该对象的`notify()`或`notifyAll()`方法唤醒它。等待的线程不会自动恢复执行,而是需要重新竞争对象...

    Java多线程wait和notify

    `notify()` 则会随机选择一个等待在该对象监视器上的线程并唤醒它,而 `notifyAll()` 则会唤醒所有等待的线程。 在实际应用中,我们通常使用 `synchronized` 关键字来确保对共享资源的访问是互斥的,同时保证 `wait...

    Java 同步锁 wait notify 学习心得

    消费者线程在移除元素后会调用`notify()`或`notifyAll()`来唤醒一个或所有等待的生产者线程,告知它们缓冲区现在有空间了。 #### 线程通信 在多线程环境中,线程之间往往需要进行通信,以避免数据竞争或死锁。`...

    Java的sychronized、wait和notify范例

    2. `notify()`:唤醒在该对象监视器上等待的一个线程。如果有多个线程等待,系统会选择一个线程,但选择策略是不确定的。唤醒的线程不会立即执行,而是变为可运行状态,需要与其他线程竞争获取锁。 3. `notifyAll()...

    一个理解wait()与notify()的例子

    - 调用`b.wait()`,这会让当前线程进入等待状态,直到另一个线程调用`b.notify()`或`b.notifyAll()`唤醒它。 - 输出完成后的总和。 - **`ThreadB`类**: - 继承自`Thread`类,重写了`run`方法。 - 在`run`方法...

    详解Java程序并发的Wait-Notify机制

    3. `notify()`只能唤醒条件队列中的一个线程,而`notifyAll()`会唤醒所有线程,但只有获得锁的线程才能继续执行。 4. 被唤醒的线程并不立即执行,而是等待锁的释放。当调用`notify()`或`notifyAll()`的线程退出`...

    Java wait和notify虚假唤醒原理

    这是Java并发编程中一个重要的概念,因为根据JVM规范,`wait()`可能会发生虚假唤醒,尽管这在实际应用中很少出现。为了解决这个问题,通常在使用`wait()`和`notify()`时,需要配合使用循环检查等待条件是否满足,而...

    浅谈java多线程wait,notify

    _java多线程wait、notify机制详解_ 在Java多线程编程中,wait和notify是两个非常重要的机制,用于实现线程之间的...通过这篇文章,读者可以更好地理解和掌握wait和notify机制,从而更好地编写高效、可靠的多线程程序。

    Java多线程中wait、notify、notifyAll使用详解

    notify()方法是唤醒一个正在wait当前对象的线程,并让被唤醒的线程拿到对象锁。该方法的调用也必须在synchronized代码块或者方法中,因为notify()方法需要当前线程必须获得对象锁。 三、notifyAll()方法 notifyAll...

    深入理解Wait、Notify和Wait与sleep区别

    3. **notifyAll()**:与`notify()`类似,但它会唤醒所有等待该对象的线程,这些线程都会尝试获取对象锁,最终只有一个成功并继续执行,其他线程仍然会在锁池中等待。 现在我们来看`sleep()`方法,它来自Thread类,...

    java-wait和notify的用法.pdf

    `notify()`方法则是用来唤醒在指定对象上等待的一个线程。当调用`notify()`时,会随机选择一个在该对象上等待的线程并将其从等待池移到可运行队列。需要注意的是,唤醒的线程并不立即执行,而是需要等到当前持有锁的...

    主线程去控制子线程wait与notify

    首先,`wait()`方法会导致当前线程进入等待状态,直到其他线程调用同一个对象的`notify()`或`notifyAll()`方法唤醒它。而`notify()`方法则会唤醒一个正在该对象上等待的线程,如果有多个线程在等待,哪个线程被唤醒...

    Java 等待唤醒机制

    Java等待唤醒机制是Java多线程编程中一个重要的概念,它涉及到线程间的协作与通信。在Java中,主要通过`Object`类提供的`wait()`、`notify()`和`notifyAll()`方法来实现这一机制。这些方法使得线程可以在特定条件下...

    等待机制与锁机制wait notify

    2. `notify()`: 这个方法用于唤醒在当前对象上等待的一个线程。但这里有一个重要特性:唤醒是随机的,系统会选择一个等待线程并将其唤醒,而其他等待线程依然保持等待状态。 3. `notifyAll()`: 与`notify()`不同,`...

    java 参赛者的比赛生活(线程休眠唤醒)

    当一个线程调用对象的 `wait()` 方法时,它会释放该对象的锁并进入等待状态,直到其他线程调用 `notify()` 或 `notifyAll()` 来唤醒它。`notify()` 唤醒单个等待线程,而 `notifyAll()` 唤醒所有等待线程。这种机制...

    浅谈Java线程间通信之wait/notify

    Java中的wait/notify/notifyAll可用来实现线程间通信,是Object类的方法,这三个方法都是native方法,是平台相关的,常用来实现生产者/消费者模式。 wait()方法将当前线程置于等待状态,直到其他线程调用notify()或...

Global site tag (gtag.js) - Google Analytics