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

为何锁定myInt时代码抛出java.lang.IllegalMonitorStateException?

为什么锁定Integer类型的myInt会抛出IllegalMonitorStateException?

问题重现

以下代码尝试通过锁定myInt实现线程交替打印,但运行时抛出java.lang.IllegalMonitorStateException:

package Thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MultiThreadingTest1 {

    public Integer myInt = 0;
    public Object lock = new Object();

    public void alternativePrinting() throws InterruptedException {
        Thread thread1 = new Thread(() -> {
            while(myInt <= 100)
                synchronized (myInt){
                    if(myInt % 2 == 0) {
                        System.out.println(Thread.currentThread().getName() + " prints " + myInt);
                        myInt++;
                        myInt.notify();
                    }
                    else
                        try {
                            myInt.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                }
        });
        Thread thread2 = new Thread(() -> {
            while(myInt <= 100)
                synchronized (myInt){
                    if(myInt % 2 == 1) {
                        System.out.println(Thread.currentThread().getName() + " prints " + myInt);
                        myInt++;
                        myInt.notify();
                    }
                    else
                        try {
                            myInt.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                }
        });
        thread1.start();
        thread2.start();
    }

    public static void main(String[] args) throws InterruptedException {
        MultiThreadingTest1 multiThreadingTest1 = new MultiThreadingTest1();
        multiThreadingTest1.alternativePrinting();
    }
}

异常信息

Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
    at java.base/java.lang.Object.notify(Native Method)
    at Thread.MultiThreadingTest1.lambda$alternativePrinting$0(MultiThreadingTest1.java:18)
    at java.base/java.lang.Thread.run(Thread.java:835)
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
    at java.base/java.lang.Object.notify(Native Method)
    at Thread.MultiThreadingTest1.lambda$alternativePrinting$1(MultiThreadingTest1.java:34)
    at java.base/java.lang.Thread.run(Thread.java:835)

核心原因分析

  • Integer是不可变类,myInt++会替换对象引用
    Java中的Integer是不可变对象,myInt++的本质是执行myInt = Integer.valueOf(myInt.intValue() + 1),这会创建一个全新的Integer对象,并让myInt变量指向这个新对象。当你进入synchronized (myInt)块时,锁定的是当时myInt指向的旧Integer实例,但执行myInt++后,后续调用myInt.notify()或myInt.wait()时,操作的是新的Integer对象,而当前线程并没有持有这个新对象的锁,直接违反了wait/notify的调用规则,因此抛出异常。

  • synchronized锁的是对象实例,不是变量
    synchronized块锁定的是括号内对象引用当前指向的实例,而不是变量本身。当myInt的引用被替换后,线程持有的锁是旧对象的,但后续操作的是新对象,自然不满足“调用wait/notify必须持有该对象锁”的要求。

  • 对比使用lock对象的情况
    当使用Object lock = new Object()作为锁时,lock变量的引用从未改变,所有synchronized块都锁定同一个对象实例,wait/notify也都是在持有该对象锁的前提下调用,完全符合规则,因此不会抛出异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 19:47:13