I am reading a book titled "Beginning Algorithms", that has examples in Java. In the chapter about queues, it explains the "blocking queue", and ... even when my background is C# and not Java, something looks funny to me.
This is part of the code ( I have omitted non relevant parts ):
public void enqueue(Object value){
synchronized(_mutex){
while(size == _max_size){
waitForNotification();
}
_queue.enqueue(value);
_mutex.notifyAll();
}
}
private void waitForNotification(){
try {
_mutex.wait();
} catch( InterruptedException e){
// Ignore
}
}
public Object dequeue() throws EmptyQueueException {
synchronized(_mutex){
while(isEmpty()){
waitForNotification();
}
Object value = _queue.dequeue();
_mutex.notifyAll();
return value;
}
}
I see two major problems.
First, if the queue is full, 5 threads are waiting to add items, and other thread dequeue 1 item, the other 5 will be released, will check at the same time that "size() == _max_size" is not true anymore and they will try to call "_queue.enqueue" 5 times, overflowing the queue.
Second, similarly the same happens with "dequeue". If several threads are blocked trying to dequeue items because the queue is empty, adding one, will cause all of them to check that the queue is not empty anymore, and all of them will try to dequeue, getting null or an exception I guess.
Am I right? I C# there is a "Monitor.Pulse" that only releases one blocked thread, would that be the solution?
Cheers.