Java生产者消费者程序触发IllegalMonitorStateException且无法终止
问题:生产者消费者模型抛出IllegalMonitorStateException且无法正常终止
代码实现
package com.example.springlearn1.demo; import java.util.LinkedList; import java.util.Random; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; class Producer implements Runnable { Random rand = new Random(); ReentrantLock lk; Condition cp; Condition cc; LinkedList<Integer> l; int cap; public Producer(LinkedList<Integer> l, ReentrantLock lk, int cap, Condition cp, Condition cc) { this.l = l; this.lk = lk; this.cap = cap; this.cp = cp; this.cc = cc; } @Override public void run() { while(true) { try { Thread.sleep(500); lk.lock(); System.out.println("In producer"); while(l.size() == cap) { cp.await(); } cc.signalAll(); if(Thread.currentThread().isInterrupted()) { System.out.println("Producer Aborting now..."); break; } l.addLast(rand.nextInt(4000)); } catch (InterruptedException e) { if(Thread.currentThread().isInterrupted()) { System.out.println("Producer Thread is interrupted."); Thread.currentThread().interrupt(); } //throw new RuntimeException(e); } finally { lk.unlock(); } } } } class Consumer implements Runnable { ReentrantLock lk; LinkedList<Integer> l; Condition cp; Condition cc; int cap; public Consumer(LinkedList<Integer> l, ReentrantLock lk, int cap, Condition cp, Condition cc) { this.l = l; this.lk = lk; this.cap = cap; this.cp = cp; this.cc = cc; } @Override public void run() { while(true) { try { Thread.sleep(1000); lk.lock(); System.out.println("In consumer"); while(l.size() == 0) { cc.await(); } cp.signalAll(); if(Thread.currentThread().isInterrupted()) { System.out.println("Aborting now..."); break; } System.out.println("Element is "+l.removeFirst()); } catch (InterruptedException e) { if(Thread.currentThread().isInterrupted()) { System.out.println("Consumer Thread is interrupted."); Thread.currentThread().interrupt(); } //throw new RuntimeException(e); } finally { lk.unlock(); } } } } public class ProducerConsumer { public static void main(String[] args) throws InterruptedException { LinkedList<Integer> queue = new LinkedList<>(); ReentrantLock lock = new ReentrantLock(); Condition cp = lock.newCondition(); Condition cc = lock.newCondition(); int capacity = 10; Thread producerThread = new Thread(new Producer(queue, lock, capacity, cp,cc)); Thread consumerThread = new Thread(new Consumer(queue, lock, capacity,cp,cc)); consumerThread.start(); producerThread.start(); System.out.println("Started both threads"); try { Thread.sleep(60000); // Run for 1 minute } catch (InterruptedException e) { System.out.println("Threads interrupted, exiting."); } producerThread.interrupt(); consumerThread.interrupt(); producerThread.join(); consumerThread.join(); } }
报错信息
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException at java.base/java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:175) at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1007) at java.base/java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:494) at com.example.springlearn1.demo.Consumer.run(ProducerConsumer.java:89) at java.base/java.lang.Thread.run(Thread.java:842) In producer
问题分析与修复
1. IllegalMonitorStateException 触发原因
这个异常的核心是线程在未持有锁的情况下调用了unlock():
- 当线程调用
Condition.await()时,方法会自动释放当前持有的锁,让其他线程可以获取锁执行逻辑。 - 如果此时线程被外部中断,
await()会抛出InterruptedException进入catch块,但你的代码中finally块会无条件执行lk.unlock(),而此时线程已经不再持有锁,导致重复释放锁,触发异常。
2. 程序无法正常终止的原因
- 中断处理逻辑错误:当线程在
await()或sleep()时被中断,catch块仅重新设置中断标志,但未退出while(true)循环,线程会继续执行循环体,无法正常终止。 - 未捕获的异常直接终止线程:
IllegalMonitorStateException属于运行时异常,未被捕获会直接终止消费者线程,而生产者线程可能仍在运行,导致程序无法按预期在1分钟后退出。
3. 修复方案
调整锁的使用结构
采用双层try-finally结构,外层处理线程中断和sleep异常,内层处理锁的获取与释放,确保unlock()仅在线程持有锁时执行。
修正中断处理逻辑
收到中断信号后直接退出循环,让线程正常终止,无需冗余的中断标志重置。
修复后的代码
package com.example.springlearn1.demo; import java.util.LinkedList; import java.util.Random; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; class Producer implements Runnable { Random rand = new Random(); ReentrantLock lk; Condition cp; Condition cc; LinkedList<Integer> l; int cap; public Producer(LinkedList<Integer> l, ReentrantLock lk, int cap, Condition cp, Condition cc) { this.l = l; this.lk = lk; this.cap = cap; this.cp = cp; this.cc = cc; } @Override public void run() { while (true) { try { Thread.sleep(500); lk.lock(); // 内层try-finally确保锁在持有状态下被释放 try { System.out.println("In producer"); while (l.size() == cap) { cp.await(); } cc.signalAll(); if (Thread.currentThread().isInterrupted()) { System.out.println("Producer Aborting now..."); break; } l.addLast(rand.nextInt(4000)); } finally { lk.unlock(); } } catch (InterruptedException e) { System.out.println("Producer Thread is interrupted."); // 收到中断后直接退出循环 break; } } } } class Consumer implements Runnable { ReentrantLock lk; LinkedList<Integer> l; Condition cp; Condition cc; int cap; public Consumer(LinkedList<Integer> l, ReentrantLock lk, int cap, Condition cp, Condition cc) { this.l = l; this.lk = lk; this.cap = cap; this.cp = cp; this.cc = cc; } @Override public void run() { while (true) { try { Thread.sleep(1000); lk.lock(); // 内层try-finally确保锁在持有状态下被释放 try { System.out.println("In consumer"); while (l.size() == 0) { cc.await(); } cp.signalAll(); if (Thread.currentThread().isInterrupted()) { System.out.println("Aborting now..."); break; } System.out.println("Element is " + l.removeFirst()); } finally { lk.unlock(); } } catch (InterruptedException e) { System.out.println("Consumer Thread is interrupted."); // 收到中断后直接退出循环 break; } } } } public class ProducerConsumer { public static void main(String[] args) throws InterruptedException { LinkedList<Integer> queue = new LinkedList<>(); ReentrantLock lock = new ReentrantLock(); Condition cp = lock.newCondition(); Condition cc = lock.newCondition(); int capacity = 10; Thread producerThread = new Thread(new Producer(queue, lock, capacity, cp, cc)); Thread consumerThread = new Thread(new Consumer(queue, lock, capacity, cp, cc)); consumerThread.start(); producerThread.start(); System.out.println("Started both threads"); try { Thread.sleep(60000); // Run for 1 minute } catch (InterruptedException e) { System.out.println("Threads interrupted, exiting."); } producerThread.interrupt(); consumerThread.interrupt(); producerThread.join(); consumerThread.join(); System.out.println("All threads terminated."); } }
修复说明
- 双层try-finally结构彻底避免了重复解锁的问题,内层finally确保锁一定会在持有状态下被释放。
- 中断处理逻辑简化,收到中断信号后直接退出循环,确保线程能快速、正常终止。
- 移除了冗余的中断标志重置操作,因为抛出
InterruptedException时中断标志已被清除,且直接退出循环无需保留标志。
内容的提问来源于stack exchange,提问作者curiousengineer
相关产品推荐
相关产品推荐

