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

使用Lock.Condition实现多线程时触发IllegalMonitorStateException求助

问题分析与解决

错误原因

你代码的核心问题是误用了Condition对象的notify()方法:notify()是Object类的原生方法,调用它要求当前线程必须持有该对象的内置synchronized锁,但你使用的是ReentrantLock显式锁,不满足这个条件,因此抛出IllegalMonitorStateException。

正确的做法是使用Condition接口提供的signal()(唤醒单个等待线程)或signalAll()(唤醒所有等待线程)方法,这两个方法才是配合Lock锁设计的唤醒API。

修正后的代码

package test;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Test {
    public static void main(String[] args) {
        final OddEvenPrinter oddEvenPrinter = new OddEvenPrinter();
        Runnable oddRunnable = () -> {
            try {
                while (true)
                    oddEvenPrinter.printOdd();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        Runnable evenRunnable = () -> {
            try {
                while (true)
                    oddEvenPrinter.printEven();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        new Thread(evenRunnable).start();
        new Thread(oddRunnable).start();
    }
}

class OddEvenPrinter {
    private final Lock lock = new ReentrantLock();
    private final Condition oddPrint = lock.newCondition();
    private final Condition evenPrint = lock.newCondition();
    private int count;

    public void printEven() throws InterruptedException {
        lock.lock();
        try {
            Thread.sleep(3000);
            while (count % 2 == 1) {
                evenPrint.await();
            }
            System.out.println("Count : " + count++);
            System.out.println("lock " + lock);
            // 替换notify()为Condition的signal()方法
            oddPrint.signal();
        } finally {
            lock.unlock();
        }
    }

    public void printOdd() throws InterruptedException {
        lock.lock();
        try {
            Thread.sleep(2000);
            while (count % 2 == 0) {
                oddPrint.await();
            }
            System.out.println("Count : " + count++);
            System.out.println("lock " + lock);
            // 替换notify()为Condition的signal()方法
            evenPrint.signal();
        } finally {
            lock.unlock();
        }
    }
}

补充说明

  • Condition是配合Lock使用的等待/通知组件,它的await()、signal()、signalAll()方法必须在当前线程持有对应的Lock锁时调用,这和Object的wait()、notify()需要持有内置锁的规则一致,但两类API绝对不能混用。
  • 你之前的代码已经正确获取了ReentrantLock锁,仅需将notify()替换为signal()即可解决异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 05:07:15