I am testing these two methods, and notify is vastly faster. What are the merits of notifyAll which would make it a better choice, provided I do not specify priorities and all threads are of the same priority?
Anton Golovin (firstname.lastname@example.org) SCJP, SCJD, SCBCD, SCWCD, OCEJWSD, SCEA/OCMJEA [JEE certs from Sun/Oracle]
Hi Anton, I changed the post. This is a better response.
What are the merits of notifyAll which would make it a better choice, provided I do not specify priorities and all threads are of the same priority?
Concurrent Programming in Java, Doug Lea, 126.96.36.199 Single notification page 191
However, in some other classes, you can reduce the context-switch overhead associated with notifications by using a single notify rather than notifyAll. Single notifications can be used to improve performance when you are sure that at most one thread needs to be woken. This applies when:
1. All possible waiting threads are necessarily waiting for conditions
relying on the same notifications, usually the exact same condition.
2. Each notification intrinsically enables at most a single thread to continue. Thus it would be useless to wake up others.
3. You can accomodate uncertainties surrounding the possibility that an interrupt and a notify may occur at about the same time. In this case, the one thread that was notified is about to terminate. You might want another thread to receive notification instead, but this is not automatically arranged. (The issue does not arise with notifyAll since all threads are woken.)
---- Java RMI, William Grosso, Chapter 11, Notify Versus NotifyAll
However, there are situations when notifyAll() is absolutely the correct choice.
One example, in a distributed chat room application, we might make the following design decisions:
There is a single centralized WhiteBoard object, which contains the transcript of the conversation.
Every remote participant is assigned a thread that sends the new lines of text.
Posting a new piece of text involves locking the whiteboard, adding the text to the whiteboard and then calling NotifyAll(). Each thread grabs the change and sends it out.
Another example occurs when the same lock is used to signal more than one type of event (and different types of events are handled by different types of waiting threads). For example, in a stockticker application, we may not want lots of information to pile up, waiting to be sent. One possible design uses a fixed-length queue to control communication. This involves the following design decisions:
There is a fixed-length queue and two threads. One thread sends messages out to the recipient, pulling them off the queue. Another thread gets messages from the sender and puts them on the queue.
Because the queue is fixed-length, however, both threads also need to wait on the queue when they get ahead. The client thread will wait for messages to come into the queue. The server thread will wait for messages to be sent, so that more space is available on the queue.
There is only one lock, but there are two events (�messages put in the queue� and �messages removed from the queue�), each intended for a different thread. Therefore, notifyAll() must be used.
[ August 29, 2004: Message edited by: Marlene Miller ]
Joined: Jul 02, 2004
Hi, Marlene! Thanks for your reply. I see that using notify is not called for in this situation because threads are waiting for different conditions (different records becoming unlocked.)
At the same time, using notifyAll is similar to splashing some super glue on the execution track of the program: it really slows it down. It becomes apparent at as low as 1000 threads, and the context-switch overhead simply bogs the program down.
At the same time, notify does cause all threads to execute, and the execution is almost sequential (with some exceptions.) I think that on Windows the implementation is designed to handle threads sequentially in the order they were created. But I obviously cannot rely on this feature.
Joined: Mar 05, 2003
I was not pleased with my response, so I came back to delete it. But I see you�ve been able to get something from what I said in spite of the way it was presented. Good.
At the same time, notify does cause all threads to execute,
I am not sure what you mean. notify causes at most one thread to execute.
I see that using notify is not called for in this situation because threads are waiting for different conditions (different records becoming unlocked.)
Suppose you have multiple threads waiting for different records to become unlocked. If all threads are waiting on one lock, notify() might select the wrong thread. If only those threads waiting on a particular record are waiting on the same lock, notify() is appropriate.
---- It's a little tricky reasoning about conditions unless we say what we mean.
condition: record n is locked notification: the state of record n has changed
condition: some records are locked notification: the state of some record has changed [ August 29, 2004: Message edited by: Marlene Miller ]
Joined: Mar 05, 2003
"All possible waiting threads are necessarily waiting for conditions relying on the same notifications, usually the exact same condition."
I get confused when I think about multiple conditions relying on multiple notifications. But I found another explanation which I think I can understand.
The Java Programming Language by Arnold, Gosling and Holmes, 10.4
Multiple threads may be waiting on the same object, possibly for different conditions. If they are waiting for different conditions, you should always use notifyAll to wake up all waiting threads instead of using notify. Otherwise you make wake up a thread that is waiting for a different condition from the one you satisfied. That thread will discover that its condition has not been satisfied and go back to waiting, while some thread waiting on the condition you did satisfy will never get awakened.
Using notify is an optimization that can be applied only when:
All threads are waiting for the same condition;
At most one thread can benefit from the condition being met; and
This is contractually true for all possible subclasses
Otherwise you must use notifyALL. If a subclass violates either of the first two conditions, code in the superclass that uses notify may well be broken. To that end it is important that waiting and notification strategies, which includes identifying the reference used (this or some other field), are documented for use by extended classes.
It sounds to me like notify may starve some threads, while notifyAll, while incurring greater overhead, will not if the scheduler operates according to some normal law of probability. In test runs on Windows XP, notify was faster and did not starve any threads. notifyAll was slower and did not starve any threads. Invocations of "notify"-awoken threads happened in a fairly contiguous manner from low to high thread names.
However, it will be notifyAll I shall be going with, because uncertainty in this project just cannot be tolerated.