我以为我完全理解notifyAll()和notify()之间的区别是什么,但后来我突然遇到了这个代码,其输出我无法弄清楚。所以我需要一些帮助来理解奇怪的输出...
注意: - 评论后// 3并取消注释// 4输出为: -
Waiting for Calculations...
Waiting for Calculations...
Waiting for Calculations...
Total is : 4950
(这似乎是合理的,好像Thread()在3个等待线程之后启动并且它调用notifyAll()并且一个等待线程将获得锁并执行所以显示总数而其他仍然等待)
并在评论// 4并取消注释// 3输出后: -
Waiting for Calculations...
Waiting for Calculations...
Waiting for Calculations...
Total is : 4950
Total is : 4950
(这很奇怪我认为在第一次输出时,当Thread()在两个等待的线程之后启动时,一个将获得锁定并且只有一个应该显示总数。但是为什么第二个总计显示为输出。)
代码: -
class Reader extends Thread {
Calculator c;
public Reader(Calculator cal) {
c = cal;
}
public void run() {
synchronized (c) {
try {
System.out.println("Waiting for calculations...");
c.wait();
}
catch (InterruptedException e) {
}
System.out.println("Total is : " + c.total);
}
}
public static void main(String arsg[]) {
Calculator calculator = new Calculator();
//Thread at 3rd and 4th position
new Reader(calculator).start();
new Reader(calculator).start();
new Thread(calculator).start(); //3
new Reader(calculator).start();
//new Thread(calculator).start(); //4
}
}
//----------------------------------------------------------------
class Calculator implements Runnable {
int total;
public void run() {
synchronized (this) {
for (int i = 0; i < 100; i++) {
total += i;
}
notifyAll();
}
}
}
代码经过修改并取自凯西塞拉 是自发唤醒的情况(其他唤醒是由jvm)
答案 0 :(得分:3)
这是一个简单的竞争条件。在一种情况下,notifyAll
只在一个线程调用wait
后发生。在另一种情况下,notifyAll
在两个线程调用wait
之后发生。在不同的条件下,没有或所有其他线程可能/将会调用wait
。
notifyAll
没有追溯性的工作。它只唤醒那些已经wait
的线程,而不是那些稍后调用wait
的线程。
答案 1 :(得分:0)
我已经得到了答案但仍然想发布我的最终修改代码,以解决我对这个问题的所有怀疑......
http://paste.ubuntu.com/11881225/
代码: -
class Reader extends Thread
{
Calculator c;
public Reader(Calculator cal)
{
c=cal;
}
public void run()
{
synchronized(c)
{
try{
System.out.println("Waiting for calculations...");
c.wait();
}
catch(InterruptedException e){System.out.println("Exception occured");}
System.out.println("Total is : "+c.total);
}
}
public static void main(String arsg[])
{
Calculator calculator=new Calculator();
new Reader(calculator).start();
new Reader(calculator).start();
new Reader(calculator).start();
new Thread(calculator).start(); // Change position of this line while experimenting
}
}
//----------------------------------------------------------------
class Calculator implements Runnable
{
int total;
public void run()
{
synchronized(this)
{
for(int i=0;i<100;i++)
{
total+=i;
}
System.out.println("Before Notify");
notifyAll();
System.out.println("After Notify");
}
}
}