notify 和 notifyall 显示奇怪的行为以等待多个线程
notify and notifyall showing weird behavior to wait of multiple threads
我以为我完全理解 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() 在两个等待线程之后启动时,第一个输出将获得锁定,只有一个应该显示总数。但是为什么第二个总数显示为输出。)
Code :-
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();
}
}
}
Code is modified and taken from kathy sierra
Is it the case of spontaneous Wakeup (other wake up is by jvm)
这是一个简单的竞争条件。在一种情况下,notifyAll
发生在只有一个线程调用了 wait
之后。在另一种情况下,notifyAll
发生在两个线程调用 wait
之后。在不同的条件下,none 或所有其他线程 could/would 调用了 wait
。
notifyAll
不能追溯。它只会唤醒那些已经 wait
ing 的线程,而不是那些稍后调用 wait
的线程。
我已经得到了答案,但我仍然想 post 我最终修改的代码解决了我对这个问题的所有疑虑....
http://paste.ubuntu.com/11881225/
Code:-
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");
}
}
}
我以为我完全理解 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() 在两个等待线程之后启动时,第一个输出将获得锁定,只有一个应该显示总数。但是为什么第二个总数显示为输出。)
Code :-
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();
}
}
}
Code is modified and taken from kathy sierra Is it the case of spontaneous Wakeup (other wake up is by jvm)
这是一个简单的竞争条件。在一种情况下,notifyAll
发生在只有一个线程调用了 wait
之后。在另一种情况下,notifyAll
发生在两个线程调用 wait
之后。在不同的条件下,none 或所有其他线程 could/would 调用了 wait
。
notifyAll
不能追溯。它只会唤醒那些已经 wait
ing 的线程,而不是那些稍后调用 wait
的线程。
我已经得到了答案,但我仍然想 post 我最终修改的代码解决了我对这个问题的所有疑虑....
http://paste.ubuntu.com/11881225/
Code:-
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");
}
}
}