aspose file tools*
The moose likes Threads and Synchronization and the fly likes Thread Communication using 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 "Thread Communication using wait() and notify()" Watch "Thread Communication using wait() and notify()" New topic
Author

Thread Communication using wait() and notify()

Rahul Nair
Ranch Hand

Joined: Dec 01, 2007
Posts: 138
Hello Ranchers!

I have some doubts about the Thread communication using the wait and notify().

Suppose, I have Operator class which accepts size for Cutting the cloths through machine and Machine class which cuts the cloths according to the specified size.

Please consider the bellow code files for both Operator and Machine Class:


and


when i execute the Operator class, i want the output (println statement) should be printed in sequence 1,2,3,4,5,6.
But i have not got the output in the above mentioned sequence.

It is printing something like 1,2,3,1,2,3,1,2,3,4,5,1,6 etc. So, obviously the Size provided by user is overwrite next time when it runs in loops and the Machine will never get that overwritten value for cutting the cloths.

So, can you please provide some solutions and detailed explanation for how can operator wait after providing the size and machine will process the size during that time ?

Any reply is highly appreciated.

Thanks,

Rahul



Jim Hoglund
Ranch Hand

Joined: Jan 09, 2008
Posts: 525
Rahul : Here is a modified version of your code. The main thing to notice is that
both threads synchronize on the same instance of a lock object. Also since the
threads have to wait on eachother, each must wait() and each must notify(). The
Operator instance, when notified, does its work only if ready is false. Similarly,
Machine, when notified, fires up to work only if ready is true. This is the common
wait/notify construct; placed in code synchronized on the same object; checking
and changing a condition flag. Jim ... ...


BEE MBA PMP SCJP-6
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 19070
    
  40

Jim Hoglund wrote:Rahul : Here is a modified version of your code. The main thing to notice is that both threads synchronize on the same instance of a lock object. Also since the threads have to wait on each other, each must wait() and each must notify(). The Operator instance, when notified, does its work only if ready is false. Similarly, Machine, when notified, fires up to work only if ready is true. This is the common wait/notify construct; placed in code synchronized on the same object; checking and changing a condition flag.

Jim ... ...


There are quite a few issues with this code.. specifically...

1. The synchronization is within the while loop. Basically, it is possible for a notification to be send after the lock is released, and before the lock is reacquired in the next iteration of the loop. If this happens the notification will be lost.

2. The while loop and if true/false construct is basically a spin wait, if the condition fails. The code will be spinning for the state -- and not using the wait() method to wait.

3. There is absolutely no reason to use the notifyAll() method here, as you need only one thread to be waken.


Anyway... try...



Henry


Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor)
Rahul Nair
Ranch Hand

Joined: Dec 01, 2007
Posts: 138
Hello,

I understand the changes i need to do.

The things we have to keep in mind for thread communication is that:

1. Both threads have to acquire lock on same instance.
2. Both threads have to wait for each others work to complete.

Thanks for your suggestions!

Rahul
Jim Hoglund
Ranch Hand

Joined: Jan 09, 2008
Posts: 525
Rahul : Thanks for responding and good luck with your project.
Henry : A bit more on the technical stuff. The while() loop models the business process and
I let it do double duty knowing that Operator won't get the lock unless the condition is false.
But as you point out, this defeats the purpose of the condition flag. I used notifyAll() just
to allow for multiple listeners. [Note to self; must wait() while(condition) not if(condition).]
Thanks and have a good week.

Jim ... ...
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 19070
    
  40

Rahul Nair wrote:
I understand the changes i need to do.

The things we have to keep in mind for thread communication is that:

1. Both threads have to acquire lock on same instance.
2. Both threads have to wait for each others work to complete.


Here are some other suggestions, that you may not have noticed from the code (from Jim and I)...

1. Never perform a wait without being about to check the state. Notice that Jim added a state flag? A blind wait is silly, as you don't know if you even need to perform the wait.

2. Never assume the state to wait. Notice that I checked before I performed the wait. It is silly to call the wait() method, when the state is already what you need.

3. Never assume the state upon return from wait. Notice that the check is in a while loop. It is possible for the state to still be wrong upon return, so don't assume.

Henry
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 19070
    
  40

Jim Hoglund wrote:
Henry : A bit more on the technical stuff. The while() loop models the business process and
I let it do double duty knowing that Operator won't get the lock unless the condition is false.
But as you point out, this defeats the purpose of the condition flag. I used notifyAll() just
to allow for multiple listeners. [Note to self; must wait() while(condition) not if(condition).]


Multiple listeners actually don't change anything in this case. This is because only one listener can grab the state.

If there are multiple listeners, and you use notifyAll(), then the first listener will wake up, grab the state, do its work, change the state, notify, and go back into a wait state. The other listeners will wake up, notice that the state is incorrect, and go back to the wait state. It is still preferred to use notify() over notifyAll().

Henry

Jim Hoglund
Ranch Hand

Joined: Jan 09, 2008
Posts: 525
My understanding is that if you have multiple waiting threads, each looking for
a different condition, and you use notify(), the one thread you wake up may not
be interested in the current condition; the notify() will be wasted. So you must
use notifyAll() to be sure the desired thread will run. Am I missing something?

Jim ... ....
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 19070
    
  40

Jim Hoglund wrote:My understanding is that if you have multiple waiting threads, each looking for
a different condition, and you use notify(), the one thread you wake up may not
be interested in the current condition; the notify() will be wasted. So you must
use notifyAll() to be sure the desired thread will run. Am I missing something?


I guess the best answer here is ... don't do this. By design, you should have all threads waiting for a condition to be waiting for the same condition. In the example shown, there are only two threads, so it's not an issue. But, in general, you should not have lots of threads waiting for different conditions using the same condition variable.

Of course, this is not always possible. The classic example is of a bounded queue. Threads that need to add elements would need to wait if the queue is full. And threads that need to take elements would need to wait if the queue is empty. And there is only one lock on the queue.

Prior to Java 5, this was an issue. This is because it was not possible to have multiple condition variables sharing the same lock. For this situation, you needed to write your own lock and condition class. Starting with Java 5, a Lock and Condition class was added -- and these classes allowed multiple condition variables to share the same lock.

Henry
Jim Hoglund
Ranch Hand

Joined: Jan 09, 2008
Posts: 525
Thanks again Henry. Good discussion.

Jim ... ...
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Thread Communication using wait() and notify()