为什么这段代码会抛出IllegalStateMonitorException异常?

3

我正在尝试使用共享对象和notifyAll()、wait()方法创建一个阻塞队列,但是这段代码会抛出IllegalMonitorStateException异常。我需要在哪里进行更改?

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;
    }
}
2个回答

4
问题在于你在调用 sharedQ 上的 notifyAllwait 时,并没有持有 sharedQ 对象上的锁。在你的方法上使用 synchronized 将确保你获得了 BlockingQueueNotifyAll 对象的锁。
来自 Object::wait 文档:

当前线程必须拥有此对象的监视器。

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
}

在您的情况下,您在不持有对象锁的情况下调用waitnotifyAll方法。

0

所以这段代码是有效的 -

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;

        }
    }

 }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接