I was actually confused about this myself, until a fellow rancher showed me the errors of my ways.
When a thread tries to enter a synchronized block, it needs to get the exclusive lock on whatever object is being used for the locking. If another thread has the lock, it goes into a blocked state. Whenever the thread that held the lock exits the synchronized block, it gives up the lock, and a blocked thread will automatically grab it and become active. You don't have to call anything special in the code.
notify and notifyAll are used to wake up waiting threads, or threads that have called the wait() method. When a waiting thread is notified, it tries to grab the exclusive lock, and if it can't, enters the blocked state. Hope that helped!
“Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning.” - Rich Cook
Originally posted by Conan Elvitaro: to avoid digging your own trap I recommend to use notifyAll only, not notify.
Generally, notifyAll() is "preferred" over notify() because either (a) the wrong thread is awoken, or (b) notifications are lost. Neither of these reasons should be considered valid. You should not have threads share locks if they are waiting for different conditions/states. And you should set variables during the synchronization block to prevent notifications from being lost.
IMO, the only reasons for using notify all is when (a) a condition is changed that can satisfy more than one thread or (b) a condition has changed when all threads must respond to. You shouldn't be using notifyAll() just because you can't get notify() to work correctly.
Henry [ March 24, 2005: Message edited by: Henry Wong ]
Valid points, however, the general consensus of this forum has been to use notifyAll() in the unlock method. You will not lose any points on the assignment using notifyAll(), but there have been situations where people have lost points for only using notify().
(a) a condition is changed that can satisfy more than one thread
This is often the case with deleted records, so once again, I would recommend using notifyAll() for this assignment.
Joined: May 24, 2004
You should not have threads share locks if they are waiting for different conditions/states.
Also, in this assignment, many are following the example from Max's book and using a collection such as a HashMap to logically lock records. In this situation, all threads are using the HashMap as the lock object, but waiting on different conditions (whether or not a specific record number exists in the HashMap). Only using notify() in the unlock can potentionally cause deadlock.
Thanks for the replys. Andrew I have updated my profile but not sure if it changes my display name. How do i do that?
I'am still a bit confused about when i should call notify or notifyAll. I understand the difference between them and I know when not to call them. But am still a bit confused about where exactly i should call one of them.
If i have a wait() call inside a synchronized block should I call notifyAll/notify at the end of that synchronized block? For example:
Is this correct use of notifyAll? If it is not, when for the above scenario should notifyAll/notify be called? Thanks in advance.
Joined: Jul 17, 2004
I told you already to call wait only inside a loop like that:
The right moment to call notifyAll is when you have a good reason to believe that maybe (or for sure) the condition (a volatile boolean field named "finished" in this case, but it can also be an other condition) has changed.
Example: inside lock:
Joined: Oct 27, 2004
Thanks for that Conan
I actually have wait() inside a while loop but left it out of the snippet i put in my last post. Sorry.
I think I understand now. But just to be sure. If i have the following: (lockedRecords is a HashMap)
Where ever I make a change to the lockedRecords I should call notify/notiyAll?
Joined: Jul 17, 2004
the major difference between your case and my case is that in I synchronize and wait on an Integer that only represents one record.
The consequence is that you really HAVE TO use notifyAll whenever you remove anything from lockedRecords. I could as well use notify, I just don't because I follow other rules than Henry does. (He made a good point though, and I will reconsider it for the future.)
So yes, call notifyAll if you want to keep the code you showed us. Unlike me you have to rely on the while (condition) and on the notifyAll to make it work.