
在Java多线程编程中,IllegalMonitorStateException 是一种常见的异常,通常在不正确使用 synchronized 关键字时抛出。本文将详细分析这个异常的原因、解决方法,并提供实际的代码示例来帮助开发者避免此问题。关键词:Java多线程、IllegalMonitorStateException解决、Java并发编程、线程同步异常处理。
大家好,我是默语,全栈开发、运维和人工智能技术的爱好者和分享者。在并发编程中,Java开发者常常会面临一些棘手的问题,IllegalMonitorStateException 就是其中之一。这类异常通常发生在线程间通信的过程中,主要与 wait()、notify() 和 notifyAll() 等方法的使用不当有关。本文将带你深入探讨如何彻底解决这个问题,避免常见的多线程陷阱。
IllegalMonitorStateException 是 Java 中的一个运行时异常,表示线程在调用 wait()、notify() 或 notifyAll() 方法时,未持有与该方法相关的对象的监视器锁(monitor lock)。
java.lang.IllegalMonitorStateException: current thread is not owner这是一个常见错误,通常发生在多线程同步中操作共享资源时。每次调用这些方法时,必须确保当前线程已经获取了对象的监视器锁,否则系统将抛出该异常。
wait() 或 notify() 🧱在Java中,wait() 和 notify() 是依赖于对象锁的同步操作。若线程在没有获取该对象的锁时调用这些方法,就会抛出 IllegalMonitorStateException。
错误示例:
public class MyClass {
public void myMethod() {
Object obj = new Object();
obj.wait(); // 错误:未在同步块中调用
}
}只有在 synchronized 代码块中,才允许调用 wait() 和 notify()。如果没有使用 synchronized 进行锁定,线程将没有权利对对象进行操作,从而导致异常。
synchronized (object) {
object.wait(); // 正确
}synchronized 块进行同步 🔑wait() 和 notify() 必须在 synchronized 块内使用,这样确保当前线程持有对象的监视器锁。
public class MyClass {
public void myMethod() throws InterruptedException {
Object obj = new Object();
synchronized (obj) {
obj.wait(); // 正确:线程已经获取锁
}
}
}在使用 wait() 或 notify() 之前,必须确保线程获取了正确的对象锁。如果你同步的不是与 wait() 或 notify() 关联的对象,异常也会发生。
错误示例:
public class MyClass {
private final Object lock = new Object();
public void myMethod() throws InterruptedException {
synchronized (new Object()) { // 错误:锁住了不同的对象
lock.wait();
}
}
}ReentrantLock 和 Condition(高级替代方案) 🌐对于更复杂的线程通信场景,Java 提供了 ReentrantLock 和 Condition,它们能够提供比 synchronized 更灵活的锁定机制。
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MyClass {
private final Lock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
public void myMethod() throws InterruptedException {
lock.lock();
try {
condition.await(); // 等待信号
} finally {
lock.unlock();
}
}
public void signal() {
lock.lock();
try {
condition.signal(); // 发送信号
} finally {
lock.unlock();
}
}
}synchronized 来调用 wait() 和 notify()public class WaitNotifyExample {
private final Object lock = new Object();
public void waitMethod() throws InterruptedException {
synchronized (lock) {
System.out.println("Thread is waiting...");
lock.wait();
}
}
public void notifyMethod() {
synchronized (lock) {
System.out.println("Thread is notified...");
lock.notify();
}
}
}IllegalMonitorStateException 的多线程通信public class ThreadCommunication {
private final Object lock = new Object();
public void doWait() {
synchronized (lock) {
try {
System.out.println("Waiting...");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void doNotify() {
synchronized (lock) {
System.out.println("Notifying...");
lock.notify();
}
}
public static void main(String[] args) throws InterruptedException {
ThreadCommunication communication = new ThreadCommunication();
Thread t1 = new Thread(communication::doWait);
Thread t2 = new Thread(communication::doNotify);
t1.start();
Thread.sleep(1000); // 确保 t1 先执行
t2.start();
}
}wait() 和 notify() 时,已经通过 synchronized 锁定了正确的对象。ReentrantLock 和 Condition 作为高级替代方案,特别是当需要更灵活的锁控制时。通过遵循这些最佳实践,你可以避免 IllegalMonitorStateException,从而编写更加健壮的并发代码。
IllegalMonitorStateException 是一种常见的Java并发异常,但它是可以通过遵循正确的同步机制轻松避免的。希望本文能够帮助你更好地理解和处理这个问题,提升你的Java并发编程能力。