• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Threads notify() and notifyAll()

 
Ranch Hand
Posts: 331
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi folks,

This code is from the K&B,



OUTPUT:
Waiting for calculation...
Waiting for calculation...
Waiting for calculation...
Total is: 4950
Total is: 4950
Total is: 4950

Well, this is OK... But even when I comment the notifyAll() method call,
I get the same output.. shouldn't there be a no output because there's no notify() or notifyAll() call? Can you please tell me why it is so?
 
Ranch Hand
Posts: 284
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Viswa,
In threads nothing can be said with gurantee. In your case it would have happened like this.. your reader threads would have started there along, before you could reach to WAIT all three associated calculator threads would have run thus giving you the output as follows-:

Waiting for calculation...
Waiting for calculation...
Waiting for calculation...
Total is: 4950
Total is: 4950
Total is: 4950



But if you keep running the program it may behave diffrently somewhere as i ran it for few times and once i got the following output-:

Waiting for calculation...
Waiting for calculation...
Total is: 4950
Total is: 4950
Waiting for calculation...


Here my first two reader threads would have started along with their calculator threads before a call for waiton c. But the third one was not that lucky one. The third reader thread started and a call to wait was sent before the associated calculator thread could start.. and when it started after that there was no notifyAll call so it kept wating as you have expected.
Actually i didnt ran the programs continiously but i added 10 more reader threads and ran them. then i again went back to three of them only as per original programs and did this excercise few times and saw the different behaviour, once i got this result too..

Waiting for calculation...
Total is: 4950
Waiting for calculation...
Waiting for calculation...


I'm not an expert here but i think it would have gone like this, more light can be thrown by the experienced ones here.
thanks
[ December 12, 2007: Message edited by: pranav bhatt ]
 
Ranch Hand
Posts: 232
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello,

This is very tricky thing

My investigation:

Comment out calculator.start = wait for ever
OR
Add Thread.sleep(5000) end of Calculator run method = wait for ever


What's triggering three treads since they're not giving any exceptions?
I could not find anything from API also...
 
Pranav Bhatt
Ranch Hand
Posts: 284
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,
i too ran your program without the notifyAll() there , i commented it and have given the explanation on that behalf.
 
Ranch Hand
Posts: 70
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Vishwa,


I looked at your code and also at first i was confused as well - but after running it multiple times i thought the following happens.

Calculator calculator = new Calculator(); // The Thread is in a New state (i.e. it has been created, but not yet started thus cannot run until start() is called.
new Reader(calculator).start();// Thread "Reader" is started, thus can runnable
new Reader(calculator).start();// same
new Reader(calculator).start();// same

at the above stage run() is called for these 3 Threads which then gets a lock on the Thread ("Calculator")

c.wait() - is called which causes the 3 Threads "Reader" to be suspended/paused, Remember that when wait() is called, the lock to the synchronized object/resource is realesed thus can be used by other Threads.

So basically here - wait() is called for a Thread that hasn't even been run (i.e. it's run method is not yet executed. you can look at the value of "total" before calling wait). and therefore notify() or notifyAll() inside run() method in class Calculator is not reachable yet.

e.g ====================================================

System.out.println("Waiting for calculation..." + c.total);

it prints:
Waiting for calculation... + 0;

====================================================

Next, calculator.start() is called therefore the Thread "Calculator" acquires the lock released by c.wait() above,
it executes it's run() method and releases the lock.


I assume that after the Calculator run() method is exited, then the Thread scheduler randomly picks between the 3 Reader threads which where suspended earlier each waiting to re-acquire the lock to the limited resource and to continue. Each Reader thread continues by re-acquiring the lock on the object Calculator and releasing it after executing the rest of the run() method, the next Reader thread does the same after getting the released lock.
Therefore, each continuing from c.wait() and executing the line

====================================================
System.out.println("Total is: " + c.total);

====================================================

Importantly the method notifyAll() here doesn't seem to have any significance because Calculator's run() method releases the lock anyway after executing; automatically making it available to the next Thread that needs it which is the 3 Reader Threads.


I'm not 100% sure of this but i this is how I interpreted the code and analysing it while running it. If anyone can correct me - i will appreciate it.


Regards,
Siphiwe Madi
SCJP 1.5 (preparation ...)
 
Jari Timonen
Ranch Hand
Posts: 232
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
JLS

Each object has it's wait set where thread is added if wait is called.
Only way thread can come out of wait is:


17.8.1
.
.
.
# A notify action being performed on m in which t is selected for removal from the wait set.
# A notifyAll action being performed on m.
# An interrupt action being performed on t.
# If this is a timed wait, an internal action removing t from m's wait set that occurs after at least millisecs milliseconds plus nanosecs nanoseconds elapse since the beginning of this wait action.
# An internal action by the implementation. Implementations are permitted, although not encouraged, to perform "spurious wake-ups" -- to remove threads from wait sets and thus enable resumption without explicit instructions to do so. Notice that this provision necessitates the Java coding practice of using wait only within loops that terminate only when some logical condition that the thread is waiting for holds.



So, maybe we have here is "spurious wake-up". ?
 
Pranav Bhatt
Ranch Hand
Posts: 284
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I agree with the explanation given by Siphiwe. But i think if you are accuring a lock on any object using wait() you have to call up notify() or notifyAll() in order to release it. Cause all the threads would be waiting on that one object. However if the call would have been like this Thread.wait(1000) then the Reader thread would have been back to runable after the 1000ms completes. So i guess if there's no notifyAll() call the thread Reader will keep waiting for ever, else if the things would have gone like the way i tried to figure out before..
Or may be it gets inturrupted to get out of waiting pool or Spontaneous Awake may bring it back to runnable.
I may be wrong so more suggestions are welcome...
[ December 12, 2007: Message edited by: pranav bhatt ]
 
Ranch Hand
Posts: 53
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Siphiwe Madi:
Hi Vishwa,
Next, calculator.start() is called therefore the Thread "Calculator" acquires the lock released by c.wait() above,
it executes it's run() method and releases the lock.




I think the new Reader("calculator").start() Thread lock is different from calculator.start() lock . Am i correct ?
 
Jari Timonen
Ranch Hand
Posts: 232
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I added some sleep to put threads to wait.. Then I added notifyAll(); Nothing. Still waiting So this concludes, that we have three threads in Calculator wait set. But, when we start new calculator thread... they disappear. Please somebody explain?




EDIT: Thread.sleep in wrong place. THIS POST DOES NOT APPLY
[ December 12, 2007: Message edited by: Jari Timonen ]
 
Siphiwe Madi
Ranch Hand
Posts: 70
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

I think the new Reader("calculator").start() Thread lock is different from calculator.start() lock . Am i correct ?





No - it is the same lock:

The locked object/resource in this context is the Thread "Calculator",
you can see this by looking at the synchronized block.


1. In class Reader

Calculator c;
synchronized(c) { //locks c which is a handle for Calculator thread
...
}


2. In class Calculator

synchronized(this) { // puts a lock on its object
...
}



basically in this case every Thread that uses the Calculator Thread needs to lock it, so it can get exclusive access to the object. This is what the 3 Reader threads are doing.

The lock is released when c.wait(); is called.

Regards,
Siphiwe Madi
SCJP 1.5 (preparation)
 
Vishwanath Krishnamurthi
Ranch Hand
Posts: 331
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

This question from K&B,




has these alternatives:

What is the result of trying to compile and run this program?
A. It fails to compile because the IllegalMonitorStateException of wait() is not dealt
with in line 7.
B. 1 2 3
C. 1 3
D. 1 2
E. At runtime, it throws an IllegalMonitorStateException when trying to wait.
F. It will fail to compile because it has to be synchronized on the this object.


Answer:
D is correct. 1 and 2 will be printed, but there will be no return from the wait call

because
no other thread will notify the main thread, so 3 will never be printed. It's frozen at line

7.





Well, I tried this one and the output was 1 2 and not 1 2 3
But if spurious-wakeup had happened then the O/P should have been 1 2 3 right?

Why is it that in this code there is a "continued-wait" when it wasn't the case with the first code..?(considering that both codes have no notify() or notifyAll())

Thanks
[ December 12, 2007: Message edited by: Vishwa Nath ]
 
Jari Timonen
Ranch Hand
Posts: 232
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Spontaneous cannot happen every time. (you can't predict nothing with Threads)
Maybe we have something that we just don't understand.

Something empties Calculator's waiting set, what it is?
 
Siphiwe Madi
Ranch Hand
Posts: 70
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think the trick in this code is that c.wait() is called on thread "Calculator" that is not even been run (i.e. whose run() method is not yet called) until calculator.start() executes and this call only happens later.)

To make it obvious that 3 Reader threads are suspended and needs a notifyAll() or notify() method to continue, change these 2 lines from the original code to the following:

=======================================================
Calculator calculator = new Calculator();
calculator.start();// insert the call to calculator.start() here
new Reader(calculator).start();
new Reader(calculator).start();
new Reader(calculator).start();
//calculator.start();// comment out this line



Output:

Waiting for thread: Calculator...100
Waiting for thread: Calculator...100
Waiting for thread: Calculator...100

=======================================================

in the above the 3 threads wait for ever (and the system hangs) and this indicates that they can only continue when they receive the notifyAll() message from some thread.


and to at least not cause the threads not to wait for ever is to limit the wait by specifying time.

e.g c.wait(2000);

Something empties Calculator's waiting set, what it is?



I think may be (i repeat "may be") that's why Calculator's waiting set is let loose.

(i.e calling c.wait() before even Calculator's run method is called.)

If someone can please assist us with this question, it would help.


Regards,
Siphiwe Madi
SCJP 1.5 (preparation ...)

[ December 12, 2007: Message edited by: Siphiwe Madi ]
[ December 12, 2007: Message edited by: Siphiwe Madi ]
 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic