| Author |
notify() vs notifyAll()
|
John Johnson
Ranch Hand
Joined: Nov 05, 2006
Posts: 39
|
|
|
I just started really wondering about these two functions. Everywhere it says that notifyAll() causes all the waiting threads (on the same lock), to wake up and start running, as opposed to notify(), which wakes up only one thread. But its impossible to have threads sharing the same lock. So only one thread will wake up and receive the lock. So than, what is the difference between these two functions. Please help me understand this.
|
 |
Henry Wong
author
Sheriff
Joined: Sep 28, 2004
Posts: 13386
|
|
There is a difference between being blocked in the wait() state, and blocked while trying to reacquire the lock. It is true that only one thread can acquire the lock, hence, all the other threads (that wakeup with notifyAll()) will not run immediately -- but they will eventually wakeup as each in turn acquire and eventually free the lock. With notify(), only one thread will wakeup to acquire the lock, and eventually free the lock. The other threads will not unblock, even when the lock is freed, because they are still in the wait() state. Henry [ December 26, 2006: Message edited by: Henry Wong ]
|
Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor)
|
 |
John Johnson
Ranch Hand
Joined: Nov 05, 2006
Posts: 39
|
|
|
Got it. Thanks Henry.
|
 |
Barry Gaunt
Ranch Hand
Joined: Aug 03, 2002
Posts: 7729
|
|
|
One extra point: you would use notify() rather than notifyAll() only if you know that exactly one other thread is waiting for the lock.
|
Ask a Meaningful Question and HowToAskQuestionsOnJavaRanch
Getting someone to think and try something out is much more useful than just telling them the answer.
|
 |
Jim Yingst
Wanderer
Sheriff
Joined: Jan 30, 2000
Posts: 18641
|
|
I don't agree with that last point at all. I have frequently used notifyAll() when there's more than one thread wating for the lock. The key is, you need to make sure that after any thread gets notified, just before it exits the sync block to return the lock on the monitor, it needs to notify() another thread. Any it must guarantee that this will occur, because if just one thread gets notified and fails to notify another thread, the chain is broken, and all remaining threads will not get notified. However this isn't that difficult to guarantee. And once you do set this up correctly, it's usually much more efficient than using notifyAll(), especially for large numbers of threads. Because no more than one thread can possibly execute the synchronized section of code at one time anyway - it's inefficient to wake 1000 threads and have 999 of them block while one executes. Better to just wake one at a time, usually. There can be some exceptions to this, but in my experience, those exceptions can usually be coded in another way that makes the notifyAll() unnecessary. The main exception that I remember is: if the monitor object must be made public, exposed to unknown code, unknown threads, then you probably need notifyAll(). Because if you don't control all the code that could possibly wait() on a given monitor, you can't guarantee that notify() will get called again. Then again, if you can't control all code that accesses a given monitor, you're usually vulnerable to other problems too, like deadlock. I strongly prefer synchronizing on private monitors for this reason. But it's not always practical.
|
"I'm not back." - Bill Harding, Twister
|
 |
Henry Wong
author
Sheriff
Joined: Sep 28, 2004
Posts: 13386
|
|
Originally posted by Barry Gaunt: One extra point: you would use notify() rather than notifyAll() only if you know that exactly one other thread is waiting for the lock.
IMHO, whether you call notify() or notifyAll() is dependant on the state that you just changed. If you changed the state, in a manner that can satisfy one waiting thread, then you call notify. If you change the state that can satisfy multiple waiting threads -- like releasing a group of semaphores, or shutting down the system (special case) -- then you call notifyAll(). I don't think it matters if you have one waiting thread, many waiting threads, or even zero waiting threads. You should design your application in a fashion where you actually don't care how many threads are waiting, if there are even any. This is why you should also (1) check the state prior to waiting, and (2) check again after waiting. Henry
|
 |
Henry Wong
author
Sheriff
Joined: Sep 28, 2004
Posts: 13386
|
|
Originally posted by Jim Yingst: I don't agree with that last point at all. I have frequently used notifyAll() when there's more than one thread wating for the lock. The key is, you need to make sure that after any thread gets notified, just before it exits the sync block to return the lock on the monitor, it needs to notify() another thread.
Jim, So you never use notifyAll() -- only notify(). When a thread wakes up, and does what it needs to do... prior to releasing the lock, it will check the state to see if another thread can be satisfied, and if yes, chain it with another notify(). Interesting, Henry
|
 |
Jim Yingst
Wanderer
Sheriff
Joined: Jan 30, 2000
Posts: 18641
|
|
Henry - not never; I do sometimes use notifyAll(). But the need hasn't been common in my experience. And I typically don't bother checking if another thread might be satisfied by the condition before calling notify - I just call notify() before relinquishing the lock, regardless (unless perhaps the nature of the algorithm ensures that it's not possible that another thread could be satisfied after this thread is done). In general, let the other thread determine whether it's satisfied with the condition. If there's no other thread, fine, the notify() call is sometimes wasted. Still seems less wasteful than notifyAll(). Perhaps my thinking is colored by my first real experience with threads in Java, debugging someone else's code that generated thousands of threads and using wait()/notifyAll(). Once I refactored it us use notify() rather than notifyAll() it got considerably faster. Probably in most situations the effect would not be so dramatic. But the experience did condition me to look for a notify() solution first in most cases. Also most of my threading code has been organized so that all threads waiting on a given monitor are waiting for the same condition. For a different condition I'd usually use a different monitor. Which isn't always possible, I know, and now java.util.concurrent.Lock allows different conditions using the same lock, great. But for most of my experience 1 condition === 1 monitor has worked well. Such situations seem to favor using notify() rather than notifyAll(). [ December 28, 2006: Message edited by: Jim Yingst ]
|
 |
 |
|
|
subject: notify() vs notifyAll()
|
|
|