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

时间:2015-07-29 17:57:32

标签: 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()并从正确的对象调用它。

2 个答案:

答案 0 :(得分:7)

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

            mutex=true;
            mutex.notifyAll();

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

使用单个锁定,不要更改它。

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

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

答案 1 :(得分:0)

如果有人需要更正代码

import java.util.concurrent.atomic.AtomicInteger;


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



static class Odd implements Runnable{
    @Override
    public void run() {
        try {
            for(int i=0;i<10;i++){
                synchronized(mutex){
                    while(mutex.get()==1){
                        mutex.wait();
                    }
                    System.out.println("odd");
                    mutex.compareAndSet(0, 1);
                    mutex.notifyAll();
                }
            }

    }catch (InterruptedException e) {
        e.printStackTrace();
    }
    }
}
static class Even implements Runnable{

    @Override
    public void run() {
        try {
            for(int i=0;i<10;i++){
                synchronized(mutex){
                    while(mutex.get()==0){
                        mutex.wait();
                    }
                    System.out.println("even");
                    mutex.compareAndSet(1, 0);
                    mutex.notifyAll();
                }
            }   

        }catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
}