You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java线程同步异常求助:IllegalMonitorStateException问题排查

Java线程同步问题解决:顺序执行与监视器异常修复

嗨,我来帮你搞定这个线程同步的问题!你遇到的java.lang.IllegalMonitorStateException和线程t2没执行的问题,根源都是没有正确使用对象的监视器锁来配合wait()和notifyAll()方法。

问题原因分析

Java里的wait()、notify()、notifyAll()这几个方法有个硬性要求:调用它们的线程必须持有该对象的监视器锁,也就是必须在synchronized(锁对象)代码块或者synchronized方法里调用。如果没这么做,就会抛出那个监视器异常。

另外你的线程顺序没按预期执行,也是因为没有用锁和等待/唤醒机制来严格控制线程的执行时机——t1还没执行完,t2可能没进入等待状态,或者t1唤醒的时候t2没在等,导致t2一直没机会执行。

正确实现方案

我们可以用一个共享的锁对象,配合synchronized块、wait()和notifyAll()来实现严格的顺序执行:

public class ThreadOrderDemo {
    // 共享的锁对象,用来控制线程的等待和唤醒
    private static final Object lock = new Object();
    // 标记t1是否执行完成
    private static boolean t1Finished = false;

    public static void main(String[] args) {
        // 线程t1:打印1-6
        Thread t1 = new Thread(() -> {
            synchronized (lock) {
                for (int i = 1; i <= 6; i++) {
                    System.out.println(i);
                }
                // 标记t1执行完成,唤醒所有等待该锁的线程
                t1Finished = true;
                lock.notifyAll();
            }
        });

        // 线程t2:打印6-1
        Thread t2 = new Thread(() -> {
            synchronized (lock) {
                // 如果t1还没完成,就进入等待状态(用循环避免虚假唤醒)
                while (!t1Finished) {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        e.printStackTrace();
                    }
                }
                // t1完成后,执行打印6-1
                for (int i = 6; i >= 1; i--) {
                    System.out.println(i);
                }
            }
        });

        // 注意启动顺序:先启动t2,让它先获取锁并进入等待状态,再启动t1
        t2.start();
        t1.start();
    }
}

关键细节说明

  • 共享锁对象:用private static final Object lock作为两个线程的共享锁,确保它们竞争同一个监视器。
  • synchronized块包裹:所有调用wait()和notifyAll()的代码都在synchronized(lock)块里,保证线程持有锁的时候才调用这些方法,彻底避免监视器异常。
  • 循环判断等待条件:用while (!t1Finished)而不是if,因为线程被唤醒后可能会出现虚假唤醒,循环判断能确保条件真的满足了再继续执行。
  • 启动顺序:先启动t2,让它先获取锁并进入等待状态,再启动t1,这样t1执行完唤醒t2的时候,t2正好在等待,能及时执行后续逻辑。

这样修改后,就能实现t1打印1-6完成后,t2再打印6-1,也不会出现监视器异常啦~

内容的提问来源于stack exchange,提问作者Kent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:11:58