尽管从同步上下文中调用notifyAll(),仍然是IllegalMonitorStateException

Ren*_*ith 2 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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

错误是

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)
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚错误的原因.我从同步上下文调用notifyAll()并从正确的对象调用它.

Nat*_*hes 7

你正在从你的线程下改变锁定.每次将布尔值设置为某个东西时,这都是一个不同的对象; 代码

            mutex=true;
            mutex.notifyAll();
Run Code Online (Sandbox Code Playgroud)

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

使用单个锁,不要更改它.

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

通常最好使用专用锁,这是您不用于任何其他目的的锁.重载具有不同用途的内容可能会导致太麻烦.