I recently saw the following implementation of enqueue for a BlockingQueue
(source)
public synchronized void enqueue(Object item)
throws InterruptedException {
while(this.queue.size() == this.limit) {
wait();
}
if(this.queue.size() == 0) {
notifyAll();
}
this.queue.add(item);
}
Why is the while loop necessary, and can the while be replaced by if (this.queue.size() == this.limit)
It seems the method enqueue is synchronized so only 1 thread at a time can be executing in the method body and make the call to wait(). Once the thread is notified, can’t it just continue onward without checking the this.queue.size() == this.limit condition again?
No. You need the while because there might be multiple threads waiting for the space in the queue to open up, and the notifyAll() calls will wake all of them up.
The wait() method actually releases the synchronisation monitor so that other threads can make progress. If it didn’t, then any thread trying to remove stuff from the queue would also get stuck waiting to enter a synchronised block in the get() method (for example).
Only one of the waiting threads will see a partially empty queue.
Actually, none of them might; the threads might have been woken up with notifyAll for some completely unrelated reason.