user3603523
user3603523

Reputation: 31

Why is this code throwing IllegalStateMonitorException

I am trying to create a Blocking Queue using notifyAll() and wait() methods with a shared object. But this code throws IllegalMonitorStateException. Where do I need to make the change?

public class BlockingQueueNotifyAll<E> {

    private Queue<E> queue;
    private int max;
    private Object sharedQ = new Object();

    public BlockingQueueNotifyAll(int size) {
        queue = new LinkedList<>();
        this.max = size;
    }

    public synchronized void put(E e) {
        while(queue.size() == max) {
            try {
                sharedQ.wait();
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
        }
        queue.add(e);
        sharedQ.notifyAll();
    }


    public synchronized E take() throws InterruptedException {

        while(queue.size() == 0) {
            sharedQ.wait();
        }
        E item = queue.remove();
        sharedQ.notifyAll();
        return item;
    }
}

Upvotes: 3

Views: 89

Answers (2)

user3603523
user3603523

Reputation: 31

So this code works-

public class BlockingQueueNotifyAll<E> {

    private Queue<E> queue;
    private int max;
    private Object sharedQ = new Object();

    public BlockingQueueNotifyAll(int size) {
        queue = new LinkedList<>();
        this.max = size;

    }

    public void put(E e) {

        synchronized (sharedQ) {
            while (queue.size() == max) {

                try {
                    sharedQ.wait();
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }

            }
            queue.add(e);
            sharedQ.notifyAll();
        }
    }

    public E take() throws InterruptedException {

        synchronized (sharedQ) {
            while (queue.size() == 0) { // replace if with an while

                sharedQ.wait();
            }
            E item = queue.remove();
            sharedQ.notifyAll();
            return item;

        }
    }

 }

Upvotes: 0

Michał Krzywański
Michał Krzywański

Reputation: 16900

The problem is that you call notifyAll and wait on sharedQ but you are not doing it while holding the lock on sharedQ object. synchronized on your methods will make sure you acquire lock on BlockingQueueNotifyAll object.

From Object::wait docs :

The current thread must own this object's monitor.

synchronized (obj) {  // here you acquire lock on obj
         while (<condition does not hold>)
             obj.wait();  // here you call wait on obj while holding the lock on this object
         ... // Perform action appropriate to condition
}

So in your case you call wait and notifyAll on object while not holding the lock on this object.

Upvotes: 4

Related Questions