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

