【问题标题】:IllegalMonitorStateException while calling notifyAll [duplicate]调用 notifyAll 时出现 IllegalMonitorStateException [重复]
【发布时间】:2020-05-11 09:37:43
【问题描述】:

我有一段代码在调用 notifyAll 时给出 IllegalMonitorException。在 enQueue() 时,线程添加数据并抛出非法监视器异常。

BlockingQueue.class:

public class BlockingQueue {
private Queue<Integer> queue = new LinkedList<>();
private int maxCount;
private Lock lock = new ReentrantLock();

BlockingQueue(int maxCount){
    this.maxCount=maxCount;
}

public  void enQueue(int d) throws InterruptedException {
    lock.lock();
    if(queue.size() >= maxCount){
        System.out.println("going to wait enqueu "+Thread.currentThread().getName() +" size "+queue.size());
        lock.wait();
    }
    System.out.println(" Adding "+d);
    queue.add(d);
    lock.notify();
    lock.unlock();
}

public  Integer deQueue() throws InterruptedException {
    lock.lock();
    if(queue.size()==0){
        System.out.println("going to wait dequeue "+Thread.currentThread().getName()+" size "+queue.size());
        lock.wait();
    }
    int data = queue.remove();
    lock.notify();
    lock.unlock();
    return data;
}}

主类:

 public class Main {
public static void main(String args[]){
    BlockingQueue queue=new BlockingQueue(10);
    Producer p = new Producer(queue);
    Consumer c = new Consumer(queue);

    Thread t1=new Thread(c,"Consumer");
    Thread t2=new Thread(p, "producer");

    t1.start();
    t2.start();
}}

生产者.类:

 public class Producer implements Runnable {
private BlockingQueue q;
Producer(BlockingQueue qu){
    this.q=qu;
}

public Integer generateWork() throws InterruptedException {
    return new Random().nextInt(100 );
}

@Override
public void run() {
    for(int i =0; i<100; i++){
        try {
            Thread.sleep(100);
            q.enQueue(generateWork());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}}

消费者类:

public class Consumer implements Runnable {

private BlockingQueue queue;
Consumer(BlockingQueue q){
    this.queue=q;
}

public void consume(int data){
    System.out.println(" consume "+data);
}

@Override
public void run() {
    for(int i=0; i < 100; i++){
        try {
            Thread.sleep(1000);
            consume(queue.deQueue());
        } catch (InterruptedException e) {
           System.out.println("interrupted");
        }
    }
}}

输出:

添加 94

线程“生产者”java.lang.IllegalMonitorStateException 中的异常

at java.lang.Object.notify(Native Method)
at BlockingQueue.enQueue(BlockingQueue.java:23)
at Producer.run(Producer.java:20)
at java.lang.Thread.run(Thread.java:748)

【问题讨论】:

  • 你能发布完整的代码来重现这个问题吗?
  • 嘿..我已经更新了代码。我不想使用条件。 ://
  • 如果您使用的是Lock,那么您必须使用Condition。但是你为什么犹豫使用Condition
  • @Slaw ConditionLock 不是强制使用的,但它是一个很棒的组合。
  • @YogeshBadke 如果您想正确使用 API。虽然您的答案可能有效,但应该或者使用synchronizedObject 的等待/通知 LockCondition 的等待/信号。使用synchronized (lock),其中lockjava.util.concurrent.locks.Lock 的一个实例,是代码异味。

标签: java multithreading thread-safety reentrantlock illegalmonitorstateexcep


【解决方案1】:

以下代码修复了问题

public class BlockingQueue {
    private Queue<Integer> queue = new LinkedList<>();
    private int maxCount;
    private Lock lock = new ReentrantLock();

    BlockingQueue(int maxCount) {
        this.maxCount = maxCount;
    }

    public void enQueue(int d) throws InterruptedException {
        lock.lock();
        if (queue.size() >= maxCount) {
            System.out.println("going to wait enqueu " + Thread.currentThread().getName() + " size " + queue.size());
            waitInternal();
        }
        System.out.println(" Adding " + d);
        queue.add(d);
        notifyInternal();
        lock.unlock();
    }

    public Integer deQueue() throws InterruptedException {
        lock.lock();
        if (queue.size() == 0) {
            System.out.println("going to wait dequeue " + Thread.currentThread().getName() + " size " + queue.size());
            waitInternal();
        }
        int data = queue.remove();
        notifyInternal();
        lock.unlock();
        return data;
    }

    private void waitInternal() throws InterruptedException {
        synchronized (lock) {
            lock.wait();
        }
    }

    private void notifyInternal() throws InterruptedException {
        synchronized (lock) {
            lock.notify();
        }
    }
}

说明: 您从不允许的非同步块调用 waitnotify。当您调用其中任何一个时,您应该对该对象进行监视器锁定。在这种情况下lock

这是一个很好的阅读为什么必须等待/通知总是在一个同步块中 https://stackoverflow.com/a/2779565/1891456

【讨论】:

    猜你喜欢
    • 2013-08-15
    • 1970-01-01
    • 2010-12-04
    • 1970-01-01
    • 2014-07-01
    • 2022-01-09
    • 1970-01-01
    • 1970-01-01
    • 2016-12-02
    相关资源
    最近更新 更多