java - 尽管从同步上下文调用了notifyAll(),但仍存在 IllegalMonitorStateException

标签 java multithreading synchronized

public class Alternate {
    static Boolean mutex = true;
    public static void main(String[] args) {
        Thread t1 = new Thread(new Odd(mutex));
        Thread t2 = new Thread(new Even(mutex));
        t1.start();
        t2.start();
    }
}

class Odd implements Runnable{
    Boolean mutex;

    Odd( Boolean mutex){
        this.mutex=mutex;   
    }

    @Override
    public void run() {
        try {
            synchronized(mutex){
                while(mutex){
                    mutex.wait();
                }
                System.out.println("odd");
                mutex=true;
                mutex.notifyAll();
                Thread.sleep(500);
            }
        }catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class Even implements Runnable{
    Boolean mutex;

    Even( Boolean mutex){
        this.mutex=mutex;
    }

    @Override
    public void run() {
        try {
            synchronized(mutex){
                while(!mutex){
                    mutex.wait();
                }
                System.out.println("even");
                mutex=false;
                mutex.notifyAll();
                Thread.sleep(500);
            }
        }catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

错误是

java.lang.IllegalMonitorStateException
    at java.lang.Object.notifyAll(Native Method)
    at com.test.concurrency.Even.run(Alternate.java:55)
    at java.lang.Thread.run(Thread.java:722)

我无法找出错误的原因。我从同步上下文中调用notifyAll(),并从正确的对象中调用它。

最佳答案

您正在从线程下更改锁。每次你将 boolean 值设置为某个东西时,那都是一个不同的对象;代码

            mutex=true;
            mutex.notifyAll();

将互斥量设置为与线程同步的对象不同的对象(因此线程尚未获取其监视器),然后对新对象调用notifyAll。

使用单个锁并且不要更改它。

锁定 boolean 值、数字包装器或字符串太容易出错,应该避免。您不仅会遇到所看到的错误,而且应用程序的其他不相关部分(可能由其他人遵循相同的做法编写)可能会锁定同一对象并导致神秘的问题。 boolean 值、数字包装器和字符串可用于 JVM 中的所有内容。最好使用范围受限的锁,以便应用程序中的任何其他内容都无法获取它。

通常最好使用专用锁,不要将其用于任何其他目的。重载具有不同用途的东西很容易引起麻烦。

关于java - 尽管从同步上下文调用了notifyAll(),但仍存在 IllegalMonitorStateException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31707794/

相关文章:

java - 是否有解决方案可以通过方法引用使方法调用函数具有动态数量的参数?

协程中的 Python 循环

python - python中ThreadPool中每个线程的超时

scala - 等待 Play 框架中的 ws future 响应

java - 当数据可用时发送数据到串口

java - 如何在不同线程中处理不同的扫描仪

java - 如何从第二个 Controller 将值传递到已打开的阶段(第一个 Controller )?

java - 使用 FileInputStream : A file is in a different file format than its extension indicates 保存 xls 文件

java - Weka K-均值距离

c# - 如何检测多线程使用?