Win a copy of Learn Spring Security (video course) this week in the Spring forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

K&B notifyAll( ) Example

 
Sindhur Sat
Greenhorn
Posts: 23
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There has been a lot of discussion on this example and I have more the add.
I removed the notifyAll() and replaced it with notify() in the the run() method of the Calculator thread and there is absolutely no difference in the output (I executed it on three different operating systems).
Also I tried to add a sleep() to make sure that all three threads are waiting before the calculator starts and hence there are three threads in the wait pool of the object calc. When notify() is called one of the three threads has to be woken up and the other two should still continue to wait right? Wrong!! Thats not what is happening.
Why do the other two threads also get notified? I think I am missing something very important.
I know the book mentions

Note that if the run() method used notify() instead of notifyAll(), there would be a chance that only one reader would be notified instead of all the readers.

Is there ever a situation where only one thread is notified? I could not find one.
I add the code here:

Please Advice,
Sindhur.
 
Bijesh Krishnadas
Ranch Hand
Posts: 31
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Does someone have an answer to this? I've been waiting to see it answered by the gurus.
Bijesh
 
Richard Quist
Ranch Hand
Posts: 96
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I confirmed this behavior on Windows using J2SE 1.4 ...and it certainly seems to run counter to the documentation for notify(). According to the 2nd edition of the Java Language Spec:
The notify method should be called for an object only when the current thread has already locked the object�s lock. If the wait set for the object is not empty, then some arbitrarily chosen thread is removed from the wait set and reenabled for thread scheduling. (Of course, that thread will not be able to proceed until the current thread relinquishes the object�s lock.)

and...
The notifyAll method should be called for an object only when the current thread has already locked the object�s lock. [B} Every thread [B] in the wait set for the object is removed from the wait set and re-enabled for thread scheduling. (Of course, those threads will not be able to proceed until the current thread relinquishes the object�s lock.)

Then, just for fun, I commented out the call to notify()....and the program still completed. I expected that it would wait forever...
[ March 03, 2004: Message edited by: Richard Quist ]
 
Sindhur Sat
Greenhorn
Posts: 23
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Richard,
You added a new twist to an already twisted problem. I tried removing the notify() like you said and guess what... it still worked exactly the way it worked with all the notify() calls. All this without even adding a timeout in the wait() call.
Interesting!!!
Sindhur.
[ March 03, 2004: Message edited by: Sindhur Sat ]
[ March 03, 2004: Message edited by: Sindhur Sat ]
 
Bijesh Krishnadas
Ranch Hand
Posts: 31
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have a hypothesis here:
1) If the object being synchronised(syncObj) is a thread by itself, then merely running this object's thread to completion does something similar to notifyAll()
below is the research I did.

Running the code as is results in all Reader threads waiting forever.
Running with line A uncommented wakes up exactly one thread.
Running with line B uncommented wakes up all threads.
Running with line C uncommented wakes up all threads.
So wat say ppl? Is this another weird but true or does the JLS actually talk about this.
Gurus, ur thoughts, plzzz.
Bijesh
 
Prabath Siriwardena
Greenhorn
Posts: 15
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
ASSUME :
ThreadA, ThreadB and ThreadC are Reader Threads.
CalculatorThread and CalThread are Calculator Threads.
Case I
ThreadA, ThreadB, ThreadC all wait on CalculatorThread to finish a certain task.
CalculatorThread has a notify() call inside it’s run() just after the expected task of Reader threads completed. But Calculator thread can run beyond that.
CalculatorThread is still alive (not dead) when ThreaA,ThreadB,ThreadC hit their wait() call.

1)Only one Reader thread will be notified.(say ThreadB)
2)It will resume operations as soon as CalculatorThread notified and it exits the synchronized block, where “notify()” resides.
3)Other Reader threads will wait(). But now their wait() method behaves as the yield() method. ( Exactly as yield. It won’t release any locks it has now. But remember it has already released the lock on CalculatorThreard object, at the time it hit the wait() call)
4)So as soon as CalculatorThread exits it’s run() method, ThreadA & ThreadC resume their operaions.

Case I I
ThreadA, ThreadB, ThreadC all wait on CalculatorThread to finish a certain task.
CalculatorThread has a notify() ( or may not have a notify()) call inside it’s run() just after the expected task of Reader threads completed. But Calculator thread can run beyond that.
CalculatorThread is not alive (dead) when ThreaA,ThreadB,ThreadC hit their wait() call.
1)NO Reader thread will be notified.
2)All reader threads will wait(). But now their wait() method behaves as the sleep() method. ( Exactly as sleep(). It won’t release any locks it has now. But remember it has already released the lock on CalculatorThreard object, at the time it hit the wait() call)

Case III
ThreadA, ThreadB, ThreadC all wait on CalculatorThread to finish a certain task.
CalculatorThread has a notify() ( or may not have a notify()) call inside it’s run() just after the expected task of Reader threads completed. But Calculator thread can run beyond that.
CalculatorThread is not alive (dead) when ThreaA,ThreadB,ThreadC hit their wait() call.
But CalThread is alive, and contains a notify() ( or may not have a notify())call inside it’s run() just after the expected task of Reader threads completed.
1)NO Reader thread will be notified, because none of them waits on CalThread object.
2)All reader threads will wait(). But now their wait() method behaves as the sleep() method. ( Exactly as sleep(). It won’t release any locks it has now. But remember it has already released the lock on CalculatorThreard object, at the time it hit the wait() call)
Case I V
ThreadA, ThreadB, ThreadC all wait on CalculatorThread to finish a certain task.
CalculatorThread has a notifyAll() call inside it’s run() just after the expected task of Reader threads completed. But Calculator thread can run beyond that.
CalculatorThread is still alive (not dead) when ThreaA,ThreadB,ThreadC hit their wait() call.

1)All Reader threads will be notified.
2)All will resume operations as soon as CalculatorThread notified and it exits the synchronized block, where “notifyAll()” resides.
Case V
ThreadA, ThreadB, ThreadC all wait on CalculatorThread to finish a certain task.
CalculatorThread has NO notify() or notifyAll() calls inside it’s run().
CalculatorThread is still alive (not dead) when ThreaA,ThreadB,ThreadC hit their wait() call.

1)No Reader thread will be notified.
2)All Reader threads will wait(). But now their wait() method behaves as the yield() method. ( Exactly as yield. It won’t release any locks it has now. But remember it has already released the lock on CalculatorThreard object, at the time it hit the wait() call)
3)So as soon as CalculatorThread exits it’s run() method, all Reader threads resume their operations.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic