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
相关产品推荐
相关产品推荐

