Java 使用2个不同线程打印奇偶数时出现非法监视异常

Java 使用2个不同线程打印奇偶数时出现非法监视异常,java,multithreading,Java,Multithreading,下面是我使用两个不同线程打印奇偶数的代码。 但是在运行代码时,我得到了非法的monitorexception 请帮助我理解为什么我会得到这个例外 class PrintOddEven { public static void main(String args[]) { Integer num = new Integer(1); Thread odd = new Thread(new Odd(num)); Thread even = new

下面是我使用两个不同线程打印奇偶数的代码。 但是在运行代码时,我得到了非法的monitorexception

请帮助我理解为什么我会得到这个例外

class PrintOddEven {

    public static void main(String args[]) {
        Integer num = new Integer(1);
        Thread odd = new Thread(new Odd(num));
        Thread even = new Thread(new Even(num));
        odd.start();
        even.start();
    }
}

class Odd implements Runnable {
    Integer num;

    public Odd(Integer num) {
        super();
        this.num = num;
    }

    @Override
    public void run() {
        while (num <= 100) {
            try {
                synchronized (num) {
                    if (num % 2 == 0) {
                        num.wait();
                    }
                    System.out.println(num);
                    num++;
                    num.notifyAll();
                    num.wait();

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

class Even implements Runnable {

    Integer num;

    public Even(Integer num) {
        super();
        this.num = num;
    }

    @Override
    public void run() {
        while (num <= 100) {
            try {
                synchronized (num) {
                    if (num % 2 != 0) {
                        num.wait();
                    }
                    System.out.println(num);
                    num++;
                    num.notifyAll();
                    num.wait();
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class-printodd偶数{
公共静态void main(字符串参数[]){
整数num=新整数(1);
线程奇数=新线程(新奇数(num));
线程偶数=新线程(新偶数(num));
奇。开始();
偶数。开始();
}
}
类奇数实现可运行{
整数数;
公共奇数(整数){
超级();
this.num=num;
}
@凌驾
公开募捐{
while(num
如果你执行这段代码,你会发现
hashcode
是不同的(这是它们的值,即1和2),那么如果
hashcode
是不同的,那么它怎么可能是同一个对象(正如@Nathan Hughes所指出的那样)。这就是你得到
java.lang.IllegalMonitorStateException

import java.util.concurrent.atomic.AtomicInteger;

class PrintOddEven {

    public static void main(String args[]) {
        AtomicInteger num = new AtomicInteger(1);
        Thread odd = new Thread(new Odd(num));
        Thread even = new Thread(new Even(num));
        odd.start();
        even.start();
    }
}

class Odd implements Runnable {
    AtomicInteger num;

    public Odd(AtomicInteger num) {
        super();
        this.num = num;
    }

    @Override
    public void run() {
        while (num.get() < 100) {
            try {
                synchronized (num) {
                    if (num.get() % 2 == 0) {
                        num.wait();
                    }
                    System.out.println(num);
                    num.getAndIncrement();
                    num.notifyAll();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Even implements Runnable {

    AtomicInteger num;

    public Even(AtomicInteger num) {
        super();
        this.num = num;
    }

    @Override
    public void run() {
        while (num.get() <= 100) {
            try {
                synchronized (num) {
                    if (num.get() % 2 != 0) {
                        num.wait();
                    }
                    System.out.println(num);
                    num.getAndIncrement();
                    num.notifyAll();
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
导入java.util.concurrent.AtomicInteger;
类打印奇偶{
公共静态void main(字符串参数[]){
AtomicInteger num=新的AtomicInteger(1);
线程奇数=新线程(新奇数(num));
线程偶数=新线程(新偶数(num));
奇。开始();
偶数。开始();
}
}
类奇数实现可运行{
原子整数;
公共奇数(原子整数){
超级();
this.num=num;
}
@凌驾
公开募捐{
while(num.get()<100){
试一试{
已同步(num){
如果(num.get()%2==0){
num.wait();
}
系统输出打印项数(num);
num.getAndIncrement();
num.notifyAll();
}
}捕捉(中断异常e){
e、 printStackTrace();
}
}
}
}
类甚至实现了可运行的{
原子整数;
公共偶数(原子整数){
超级();
this.num=num;
}
@凌驾
公开募捐{

while(num.get())整数对象是不可变的。当您更改其值时,您将用新实例替换变量引用的对象。线程获取num引用的对象上的锁,然后递增该数字,从而用另一个对象替换该对象。然后线程对num引用的对象调用notifyAll,这与它获取锁的对象不同。你不允许这样做,这就是非法监视器状态异常告诉你的

TLDR:锁不在变量上,而是在对象上。增加不可变对象的值会将该对象换成另一个对象,其中没有任何对象获得锁


使用一个不用于任何其他用途的专用锁,并将其传递给奇数和偶数对象。

除非您解释为什么这会产生差异,否则此答案没有用处。
import java.util.concurrent.atomic.AtomicInteger;

class PrintOddEven {

    public static void main(String args[]) {
        AtomicInteger num = new AtomicInteger(1);
        Thread odd = new Thread(new Odd(num));
        Thread even = new Thread(new Even(num));
        odd.start();
        even.start();
    }
}

class Odd implements Runnable {
    AtomicInteger num;

    public Odd(AtomicInteger num) {
        super();
        this.num = num;
    }

    @Override
    public void run() {
        while (num.get() < 100) {
            try {
                synchronized (num) {
                    if (num.get() % 2 == 0) {
                        num.wait();
                    }
                    System.out.println(num);
                    num.getAndIncrement();
                    num.notifyAll();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Even implements Runnable {

    AtomicInteger num;

    public Even(AtomicInteger num) {
        super();
        this.num = num;
    }

    @Override
    public void run() {
        while (num.get() <= 100) {
            try {
                synchronized (num) {
                    if (num.get() % 2 != 0) {
                        num.wait();
                    }
                    System.out.println(num);
                    num.getAndIncrement();
                    num.notifyAll();
                }

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