java - 在给定的示例代码中什么可能导致 IllegalMonitorStateException

标签 java multithreading

我正在尝试学习java并发编程。请检查我的示例代码并帮助我理解为什么我会收到“java.lang.IllegalMonitorStateException”,即使我在同步上下文中调用了 wait() 和 notification。

public class Test {

    public static void main(String[] args) throws Exception {    
        Test t1 = new Test();
        t1.m1();
    }

    private void m1() {
        Example ex = new Example();
        Thread t1 = new Thread(ex);
        t1.start();
        synchronized (ex) {
            System.out.println("waiting");
            try {
                wait();
            } catch (Exception e) {
                e.printStackTrace();
            }    
        }    
    }

    public class Example implements Runnable {    
        @Override
        public void run() {
            System.out.println("Running");
            notifyMethod();
        }

        private void notifyMethod() {
            System.out.println("Notifying");
            synchronized (this) {
                try {
                    Thread.sleep(1000);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                notify();
            }
        }
    }
}

我期望“等待、运行、通知”,但实际输出是:

waiting
Running
java.lang.IllegalMonitorStateException
Notifying
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:502)
    at examples.Test.m1(Test.java:18)
    at examples.Test.main(Test.java:8)

最佳答案

首先,我认为在 Runnable 上同步不是一个好主意(在您的情况下是Example)。您可以在 this 上同步,或者更好的是在专用的 Object 上同步,在我的示例中即为 lock编辑:Runnable上同步与使用this相同,但对我来说它看起来更好。直觉告诉我可能还有更多的事情,但我不是这个领域的专家。专用锁 Object 总是更好,请阅读 this article如果您想了解有关该主题的更多信息。

然后,在同步时,您必须对同一对象调用wait():lock.wait()。如果您在 this 上进行同步,则调用 this.wait() 或仅调用 wait()

当您想要通知等待线程时,您必须再次同步lock并对该对象调用notify():lock.notify( )。同步中的监视器和您调用 notify() 的对象都必须与您调用 wait() 的对象完全相同。

这是一个有效的代码:

public class Test {
  public static final Object lock = new Object();

    public static void main(String[] args) throws Exception {    
        Test t1 = new Test();
        t1.m1();
    }

    private void m1() {
        Example ex = new Example();
        Thread t1 = new Thread(ex);
        t1.start();
        synchronized (lock) {
            System.out.println("waiting");
            try {
                lock.wait();
            } catch (Exception e) {
                e.printStackTrace();
            }    
        }    
    }


    public static class Example implements Runnable {    
        @Override
        public void run() {
            System.out.println("Running");
            notifyMethod();
        }

        private void notifyMethod() {
            System.out.println("Notifying");
            synchronized (lock) {
                try {
                    Thread.sleep(1000);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                lock.notify();
            }
        }
    }
}

关于java - 在给定的示例代码中什么可能导致 IllegalMonitorStateException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56143664/

相关文章:

java - 使用集合类型重载的方法无法按预期工作

java - Spring 表达式语言 - 确定是否定义了 servletContext 变量

java - 并发方法设计的数据类型

c# - NUnit 3.X.X 异步测试

c - 使用线程传输文件

java - 对象树结构的 JSON 序列化

java - 使用声明字段反射提供的方法

java - 使用recyclerview从fragment中的firebase获取数据

Python3 Process 对象从不加入

c++ - 作为 .dll 的一部分运行 .exe 的 main()