aspose file tools*
The moose likes Threads and Synchronization and the fly likes wait and notify Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "wait and notify" Watch "wait and notify" New topic
Author

wait and notify

Tom Johnson
Ranch Hand

Joined: May 11, 2005
Posts: 142
This example is taken straight from a Java 2 revision for the programmer exam.

1. class ThreadA {
2. public static void main(String [] args) {
3. ThreadB b = new ThreadB();
4. b.start();
5.
6. synchronized(b) {
7. try {
8. System.out.println("Waiting for b to complete...");
9. b.wait();
10. } catch (InterruptedException e) {}
11. }
12. System.out.println("Total is: " + b.total);
13. } // end main
14.} // end Class
15.
16.class ThreadB extends Thread {
17. int total;
18.
19. public void run() {
20. synchronized(this) {
21. for(int i=0;i<100;i++) {
22. total += i;
23. }
24. notify();
25 }
26. }
27.}

Basically the main thread waits for b to do a calculation and prints result. The book explains that when b is started, main continues and gets lock on b, enters its synchronized block. Then wait() on b makes it release the lock and wait until b calls notify to tell it its done calculating. Main can then read the data when selected to run again by JVM, having regotten lock for b. And we're hunky dory.

BUT, what happens it b is lightning fast and its run method is called b4 main get lock on b and calls wait etc (ie b4 main gets to its synch block), which can happen as thread execution is indeterminate. b is in its synchronized block with lock on "this", doing the calculation so main cant enter its synch block.
b completes, and calls notify and exits its synch block. So main can now get lock on b and go into its synch block...but it then calls wait() on b expecting to be notified soon of a calculation completion. But b has exited its synch block earlier and notify() will never be called - is main stuck for ever waiting here???(obviously we could pass a timeout to wait() but that wasnt the case in the code in the book)

cheers
//Tom


<a href="http://faq.javaranch.com/java/UseCodeTags" target="_blank" rel="nofollow">Use Code Tags!!</a>
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24187
    
  34

Yes, main() would be stuck forever waiting. This is called a "race condition", and it happens often in sloppy programs. It's one example of why programming with threads is hard. Congratulations for seeing that it could happen, though -- this means you've got what it takes to be good at it!

Another way to deal with this is to give ThreadB a boolean member variable "completed" which is set to true after the thread is done, and then have main() do something like



Because "completed" is used by multiple threads, it should always be read and updated in synchronized blocks.


[Jess in Action][AskingGoodQuestions]
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
Neat question, Tom, and it's exposing some things I don't know.

Would "volatile" be sufficient for a public boolean like "completed"? This looks to be exactly the situation described in what I've read about volatile.

Would join(b) have the same risk as wait() if b happens to finish first?


A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
Tom Johnson
Ranch Hand

Joined: May 11, 2005
Posts: 142
b.join() in main would put the current thread (ie main) into a waiting state until the thread b completed its run method and died. In that sense main would only the lock on b after its calculation was completed aand b died and main could read the total.
Hence if the calculation is only done once (like in example) then i think b.join() will suffice.

In a more complex case this wont work:
Above b.join() method assumes the calculation is to be done only once ever and now b then dead, after exiting synch block and run. In a real case, I suppose b would repeat the calculation (say downloading stock data or something) via an infinite while loop in the run method.
If the situation arose which i described in my first post, main wouldnt actually get infinitely stuck, i think it would however miss the first calculation result, as it wasnt set up to be waiting when b called notify. So in this scenario of repeated b calculation, join() is no good as main will never run as theres an infinite while loop in b.

//Tom
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
Makes good sense. The run() as given does a finite loop and dies, so I thought of join(). If run() were to give periodic results ... ping a web site all day and tell you if the response time is over 2 seconds ... I'd go for some kind of pub-sub and not make A wait on B at all.
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24187
    
  34

Gotta be careful here if you start to experiment. Note that the implementation of join() uses wait/notify on the Thread object itself, and so this program (which also calls Thread.notify() ) will interact with it. In practice, wait()ing on a Thread is quite rare, so this doesn't come up too often -- but it's a real issue.
Warren Dew
blacksmith
Ranch Hand

Joined: Mar 04, 2004
Posts: 1332
    
    2
Stan James:

Would "volatile" be sufficient for a public boolean like "completed"? This looks to be exactly the situation described in what I've read about volatile.

It has been a while since I looked at the specifics, but I believe that with the Java memory model, "volatile" would not have sufficed prior to Java 1.5. I think this may have been fixed in Java 1.5. I may be thinking of "long"s, though, as they are less thread safe due to nonatomic reads and writes of the two halves of the long; or maybe it's that "volatile long"s haven't been fixed even in 1.5.

I always use explicit synchronization rather than relying on "volatile", myself.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: wait and notify