Java报错”IllegalMonitorStateException”的原因以及解决办法

  • Post category:Java

Java中的IllegalMonitorStateException是在使用synchronized代码块或方法时抛出的一种异常,它表示当前线程试图等待、通知或唤醒另一个线程时,当前线程没有拥有此对象的监视器锁。下面是可能引发该异常的两个示例:

示例一:

public class Example {
    public synchronized void methodA() {
        System.out.println("methodA");
        methodB();
    }

    public synchronized void methodB() {
        System.out.println("methodB");
    }
}

public class Main {
    public static void main(String[] args) {
        Example obj = new Example();
        obj.methodA();
    }
}

在上面的代码中,当methodA被调用时,methodB也被调用,但进入methodB时已经释放了对象的监视器锁,因此在等待、通知或唤醒另一个线程时会抛出IllegalMonitorStateException异常。

解决办法:要解决这种情况,需要使用同步块(synchronized block)而不是同步方法(synchronized method)。例如,我们可以修改methodAmethodB的代码如下:

public class Example {
    public void methodA() {
        System.out.println("methodA");
        synchronized (this) {
            methodB();
        }
    }

    public void methodB() {
        System.out.println("methodB");
    }
}

public class Main {
    public static void main(String[] args) {
        Example obj = new Example();
        obj.methodA();
    }
}

示例二:

public class Example {
    public void method() {
        synchronized (this) {
            wait();
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Example obj = new Example();
        obj.method();
    }
}

在上面的代码中,wait方法必须在同步块中调用,否则会抛出IllegalMonitorStateException异常。

解决办法:我们需要确保在调用wait方法之前获取对象的监视器锁。例如,我们可以修改method方法的代码如下:

public class Example {
    public void method() throws InterruptedException {
        synchronized (this) {
            wait();
        }
    }
}

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Example obj = new Example();
        synchronized (obj) {
            obj.method();
        }
    }
}

在上面的代码中,我们获取Example对象的监视器锁并在同步块中调用method方法,这样就可以避免抛出IllegalMonitorStateException异常。