如何解决 java.lang.IllegalMonitorStateException 异常问题?亲测有效的解决方法!

问题分析

java.lang.IllegalMonitorStateException 是一个运行时异常,通常在操作线程同步代码时触发。这类异常的根本原因是线程尝试执行同步操作(如 wait()notify()notifyAll())时,未获取到目标对象的监视器锁。


报错原因
  1. 未获取锁
    • 调用 wait()notify()notifyAll() 方法的对象需要持有其监视器锁,但线程没有同步到该对象。
  2. 同步块问题
    • 没有在同步块(synchronized)中调用同步方法。
  3. 错误的锁对象
    • 使用了错误的对象作为同步锁,导致没有持有正确的监视器。

示例报错代码

以下代码会触发 IllegalMonitorStateException

public class IllegalMonitorStateDemo {
    public static void main(String[] args) {
        Object lock = new Object();

        // 在未同步的情况下调用 wait() 方法
        try {
            lock.wait(); // 会抛出 IllegalMonitorStateException
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

错误信息:

Exception in thread "main" java.lang.IllegalMonitorStateException
    at java.base/java.lang.Object.wait(Native Method)
    at IllegalMonitorStateDemo.main(IllegalMonitorStateDemo.java:8)

解决思路
  1. 确保同步块的使用

    • 调用 wait()notify()notifyAll() 时,必须将相关代码放入 synchronized 块中。
  2. 检查锁对象

    • 确保 synchronized 块的对象与调用同步方法的对象一致。
  3. 避免嵌套锁问题

    • 保证线程持有的锁不会被无效释放或遗漏。
  4. 理解锁的作用范围

    • 确认哪些线程需要等待和通知,并正确管理监视器锁。

解决方法

示例修正代码 1:正确使用同步块

public class FixedMonitorStateDemo {
    public static void main(String[] args) {
        Object lock = new Object();

        // 在同步块中调用 wait 方法
        synchronized (lock) {
            try {
                System.out.println("Thread is waiting...");
                lock.wait(); // 正确用法
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

示例修正代码 2:正确使用 notify()

public class NotifyExample {
    public static void main(String[] args) {
        Object lock = new Object();

        Thread waitingThread = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("Waiting thread is waiting...");
                    lock.wait();
                    System.out.println("Waiting thread is resumed.");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread notifyingThread = new Thread(() -> {
            synchronized (lock) {
                System.out.println("Notifying thread is notifying...");
                lock.notify(); // 通知正在等待的线程
            }
        });

        waitingThread.start();
        try {
            Thread.sleep(1000); // 确保 wait 先执行
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        notifyingThread.start();
    }
}

输出结果:

Waiting thread is waiting...
Notifying thread is notifying...
Waiting thread is resumed.

总结
  1. 正确理解同步方法的锁机制
    • 调用 wait()notify()notifyAll() 时,必须获取对象的监视器锁。
  2. 使用同步块包裹相关操作
    • 始终在 synchronized 块中操作共享资源。
  3. 确认锁对象的一致性
    • 确保锁对象是共享的且唯一的。
  4. 排查竞争条件
    • 在多线程环境中,避免未按顺序调用 wait()notify() 方法。

通过这些方法,IllegalMonitorStateException 异常问题可以轻松解决。按照上述流程排查,逐步验证和修复代码,让你的多线程程序更加健壮。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值