【问题标题】:Why am I getting IllegalMonitorStateException for the Thread t1为什么我收到线程 t1 的 IllegalMonitorStateException
【发布时间】:2023-03-05 05:44:01
【问题描述】:

以下代码出现此错误

First thread about to sleep
thread 1  run
Boolean assignment done.
Woke up and about to invoke wait()
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:502)
    at IncorrectSynchronization$1.run(HelloWorld.java:23)
    at java.lang.Thread.run(Thread.java:748)

当线程 t1 处于休眠状态时,我从另一个线程将锁修改为 false。 然后它抛出这个 IllegalMonitorStateException。还是同一个对象,为什么修改值会导致IllegalMonitorStateException?

当我从同步块内的另一个线程将锁修改为 false 时,我不再收到该错误。谁能解释一下幕后发生的事情的原因?

public class HelloWorld{

   public static void main( String args[] ) throws InterruptedException {
        SampleTest.runExample();
    }
}

class SampleTest{

    Boolean flag = new Boolean(true);

    public void example() throws InterruptedException {

        Thread t0 = new Thread(new Runnable() {

            public void run() {
                synchronized (flag) {
                    try {
                        while (flag) {
                            System.out.println("First thread about to sleep");
                            Thread.sleep(2000);
                            System.out.println("Woke up and about to invoke wait()");
                            flag.wait();
                            System.out.println("wait() called");

                        }
                    } catch (InterruptedException ie) {

                    }
                }
            }
        });

        Thread t1 = new Thread(new Runnable() {

            public void run() {
                System.out.println("thread 1  run");
                flag = false;
              }
        });

        t0.start();
        Thread.sleep(200);
        t1.start();
        t0.join();
        t1.join();
    }

    public static void runExample() throws InterruptedException {
        SampleTest test = new SampleTest();
        test.example();
    }
}

【问题讨论】:

    标签: java multithreading locking wait synchronized


    【解决方案1】:

    问题出在这一行:

    flag = false;
    

    这会将flag 布尔变量的引用 从原来的Boolean 对象(由不应使用的已弃用的构造函数创建)更改为预先创建的@987654325 @实例(由于autoboxing)。当第一个线程调用flag.wait() 时,对象不再与它用于同步的对象相同,因此是IllegalMonitorStateException

    在这种情况下,最好使用AtomicBoolean 并在另一个线程中改变它的值:

    AtomicBoolean flag = new AtomicBoolean(true);
    

    现在第二个线程可以更新同一个对象的值。它还应该通知正在等待对象的第一个线程(例如wait()notify() 也需要在调用它的对象上进行同步):

    Thread t1 = new Thread(new Runnable() {
    
         public void run() {
             synchronized(flag) {
                 System.out.println("thread 1  run");
                 flag.set(false);
                 flag.notify();
             }
           }
     });
    

    【讨论】:

    • 但是在同步块内做flag = false;应该改变引用,对吧?但这不会引发异常
    • 请注意,在这种情况下,flag = false不会创建新的 Boolean 实例,但 new Boolean(true)(永远不应使用)会。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多