Can notify wake up the same thread multiple times? Can notify wake up the same thread multiple times? multithreading multithreading

Can notify wake up the same thread multiple times?


My answer has some implementation specific information. It is based on my working knowledge of Sun JVM and other thread library behavior.

If two producer threads invoke notify, is it guaranteed that two distinct waiting consumer threads will be awoken?

No it is not. There is no guarantee that there will be any consumers awoken. What is guaranteed is that if there are 2 threads that are waiting, then 2 different threads will be put into the run queue.

Or can it be that two notify()s fired shortly after each other cause the same comsumer thread to be queued for wakeup twice?

No. Two notify() calls will not cause the same consumer thread to be queued twice. It may however, cause one thread to be awoken and there may not be other threads waiting, so the second notify() call may do nothing. Of course the thread could have been awoken and then gone right back waiting again and so get the second notify() call that way, but I don't think think that is what you are asking.

Does java have some atomic internal operation for waking up threads exactly once?

Yes. The Thread code has a number of synchronization points. Once a thread has been notified it is moved out of the wait queue. Future calls to notify() will look into the wait queue and not find the thread.

One more important point. With producer/consumer models, always make sure you are testing the condition in a while loop. The reason is that there is race conditions with consumers that are blocked on the lock but not waiting on the condition.

 synchronized (workQueue) {     // you must do a while here     while (workQueue.isEmpty()) {         workQueue.wait();     }     workQueue.remove(); }

Consumer1 could be waiting on workQueue. Consumer2 could be blocked at the synchronized but in the run-queue. If something is put into the workQueue and workQueue.notify() is called. Consumer2 is put into run-queue now but is behind Consumer1 who is there first. This is a common implementation. So Consumer1 goes in a removes the item from the workQueue that Consumer2 was notified about. Consumer2 has to test again if the workQueue is empty otherwise remove() will throw because the queue is empty again. See here for more details of the race.

It is also important to realize that spurious wakeups have been documented so the while loop protects against a thread being awoken without a wait() call.

All this said, if you can reduce your producer/consumer code by using a BlockingQueue as recommended in other answers then you should do so. The BlockingQueue code already has solved all of these issues.


Yes, What you describe can happen.

As described in the javadoc, notify wakes an arbitrary thread. So if your thread is finished and has called wait before the next notify, then it is one of the arbitrary candidates for waking.

I have extensive experience with multithreaded applications, and I find that I use one of these two patterns:

  1. There are multiple sleeping threads which need to wake up on an event, and the order in which they wake doesn't matter. In this case, I use notifyAll to wake them.

  2. There is one sleeping thread which needs to wake up on an event. In this case, I use notify to wake it.

If I ever have a situation where there are multiple sleeping threads and I want to only wake one of them, I use a different design to achieve this. Basically, I build something out myself so that there is no arbitrary decision being made by the runtime environment. I always want to know exactly what will wake.

I break down a design into one of these two scenarios, or I use something from the java.util.concurrent package. I never have problems with spurious notifications, but I am also very careful on the objects I use for locking. I tend to create vanilla Object instances whose only purpose is to be the target of a lock operation, but occasionally I'll use an object whose class type is well-defined and under my control.


From the javadoc for notify():

The choice of which thread to notify "is arbitrary and occurs at the discretion of the implementation"

It will almost certainly not be a "fair" (as the term is used in computer science and parallelism) algorithm for waking threads. It's entirely possible that the same thread is woken up twice in quick succession. Also note that spurious notifications are also possible.

In general, I agree with the comments that suggest using a BlockingQueue implementation instead of doing this yourself.