Win a copy of Murach's Python Programming this week in the Jython/Python forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Synchronization example in KS&BB  RSS feed

 
Jay Bromley
Ranch Hand
Posts: 48
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello all,
First, off thanks all involved for providing an excellent Java resource and thanks se�ores Sierra and Bates for an excellent book on SCJP. On to the question.
I've been studying for the SCJP using the KS&BB book and have a question regarding an example on page 533 (the calculator/reader example that demonstrates notifyAll()) in the Threads chapter. My understanding is that very little is guaranteed by the JVM when it comes to threads. For example, the thread started first won't necessarily run or complete first. Does this mean that the example could deadlock?
Let us say that the calculator threads runs before one of more of the reader threads. It grabs its own lock and gets busy calculating. In these moments, even if the remaining threads get a chance to run they won't since they're blocking on the Calculator Thread object. The calculation finishes and the Calculator notifies everyone that it is done. At this point the remaining threads can grab the Calculator object lock (one at a time, of course) and start waiting for a notification that will never come since it already passed - deadlock!
I repeatedly tried running the example and it did seem to deadlock a couple times in numerous (more than 200 runs). Oddly enough, when I rewrote the example implementing Runnable the deadlocks were more frequent. Investigation seemed to tell me the above described scenario was occurring.
SO, is it conceivable that this example deadlocks, or is something else going on? Why does the version I made using Runnables deadlock more frequently (more method calls?)? Finally, if this example may deadlock, how could one avoid this problem in practice: time outs, synchronizing the start of the calculation?
Thank you and regards,
Jay
 
William Asher
Greenhorn
Posts: 25
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It's been a few years since Jay's post, but it appears no one seems to have an answer. I ran into the same thing today when trying to understand the same example, which in the current edition of "Sun Certified Programmer for Java 6 Study Guide" is in chapter 9 on page 752. The Reader class in the book extends Thread, and when run numerous times deadlocks. In three forever loops in an execution shellscript, it deadlocked once after 21 trials, once after 95 trials, and once after 3 trials. The code in the book is as follows:


Like Jay (and independently of him) I tried rewriting the code using the Runnable interface, primarily to get practice writing code that way, which Sierra and Bates say is preferable from a design perspective. Similarly to his experience, the code deadlocks very frequently - after only one or two trials. Here is my re-written Runnable version:



To repeat Jay's question: why does the Runnable version deadlock more frequently? Also, what can be done to prevent deadlock in this example?

Thanks.
 
Siva Masilamani
Ranch Hand
Posts: 385
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Answer to prevent deadlock is given in the other program in the same book which states that use some common object between them and make sure to notify only if something is waiting to get notified.

I believe the book uses the example for machine cutting shape...

why does the Runnable version deadlock more frequently


I think it is JVM specific not depends on either you extends Thread class or implements Runnable interface.
 
William Asher
Greenhorn
Posts: 25
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You are correct. The answer is hinted at on the page following the code I quoted, by reference to the sewing machine example. I think the problem is not technically "deadlock", but just the fact that some of the "main" threads (the three Readers) might execute before the other thread (the Calculator) gets going, so the Reader threads will be waiting in vain sometimes.

The solution is to check on some conditional expression, and only wait if the thing you're waiting for has not yet happened (from p. 754).

Here is my revised Runnable version, and it appears to work fine after more than 1000 invocations. It uses an instance variable (calcStarted) in the Calculator class to permit the conditional execution of the wait() method.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!