简体   繁体   English

当使用2个不同的线程打印奇数偶数时,animalMonitorException

[英]illegalMonitorException while printing odd even numbers using 2 different threads

Following is my code to print odd even number using 2 different threads. 以下是我的代码使用2个不同的线程打印奇数。 But while running the code, i am getting IllegalMonitorException. 但是在运行代码时,我得到了IllegalMonitorException。

Please help me to understand why I am getting this exception. 请帮助我了解为什么会出现此异常。

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();
            }
        }
    }
}

Please help me to understand why this code is throwing illegalMonitorException 请帮助我了解为什么此代码会引发非法监视器异常

    Integer num = new Integer(1);
    System.out.println(num.hashCode());
    num++;
    System.out.println(num.hashCode());

If you execute this piece of code then you will find hashcode is different (which is their value ie 1 and 2) so if hashcode is different then how could it be same object (as pointed out by @Nathan Hughes). 如果执行这段代码,则会发现hashcode码是不同的(即它们的值,即1和2),因此,如果hashcode不同,那么它怎么可能是同一对象(如@Nathan Hughes所指出的)。 So that is the reason you're getting java.lang.IllegalMonitorStateException 因此,这就是您获取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();
            }
        }
    }
}

Integer objects are immutable. 整数对象是不可变的。 When you change its value you're replacing the object being referenced by the variable with a new instance. 更改其值时,您将用新实例替换变量引用的对象。 A thread acquires the lock on the object referenced by num, then increments the number, thereby replacing the object with another one. 线程获取对num引用的对象的锁定,然后递增该数字,从而用另一个对象替换该对象。 Then the thread calls notifyAll on the object referenced by num, which is a different object from the one that it acquired the lock on. 然后,线程对由num引用的对象调用notifyAll,该对象与它获取锁定的对象不同。 You're not allowed to do that, that's what the IllegalMonitorStateException is telling you. 您不允许这样做,这就是IllegalMonitorStateException告诉您的。

TLDR: the lock isn't on a variable, it's on an object. TLDR:锁不在变量上,而是在对象上。 Incrementing the value of an immutable object swaps that object out for a different object where nothing has acquired its lock. 增加不可变对象的值会将该对象换成另一个没有获得其锁的对象。

Use a dedicated lock that you don't use for anything else, and pass that to your Odd and Even objects. 使用专用的锁,该锁不用于其他任何用途,并将其传递给奇数和偶数对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM