谁能解释为什么这个程序显示 IllegalMonitorStateException?

时间:2021-02-10 07:33:11

标签: java multithreading exception parallel-processing illegalmonitorstateexcep

class Lock 
{
    public int l=0;
}

class Numbers extends Thread
{
    final Lock lock;
    Numbers(Lock l,String name)
    {
        super(name);
        lock=l;
    }
    
    public void run()
    {
        synchronized(lock)
        {
            for(int i=0;i<100;i++)
            {
                if(i==50)
                {
                    try
                    {
                        while(lock.l==0)
                        {
                            System.out.println("Waiting for letters to complete");
                            wait();
                            System.out.println("Wait complete");
                        }
                    }
                    catch(InterruptedException e)
                    {
                        System.err.println("ERROR");
                    }
                }
                System.out.println(i);
            }
        }
    }
}

class Letters extends Thread
{
    final Lock lock;
    Letters(Lock l,String name)
    {
        super(name);
        lock=l;
    }
    
    public void run()
    {
        synchronized(lock)
        {
            for(int i=65;i<=90;i++)
                System.out.println((char)i);
            lock.l=1;
            notify();
        }
    }
}

public class MyClass
{
    public static void main(String args[])
    {
        Lock l=new Lock();
        Numbers n=new Numbers(l,"Numbers");
        Letters let=new Letters(l,"Letters");
        n.start();
        let.start();
    }
}

我打算通过这个程序打印最多 49 的数字,然后等到 Letters 线程完成打印字母,然后控制返回到 Numbers 线程并完成执行。

但是此代码在打印最多 49 个数字后抛出异常,然后打印 A-Z,然后执行失败,显示 IllegalMonitorStateException

1 个答案:

答案 0 :(得分:4)

<块引用>

执行失败,显示 IllegalMonitorStateException。

这是由于对 notify(); 方法的调用不遵守其 contract:

<块引用>

唤醒在此对象监视器上等待的单个线程。 (……) 这个方法只能被拥有者的线程调用 此对象的监视器。

同样适用于 wait 方法:

<块引用>

此方法只能由作为此对象监视器所有者的线程调用。

TL:DR

您在错误的上调用 waitnotify()隐式锁实例返回this).

分别将这些调用更改为:

lock.notify();lock.wait();

基于您的代码运行示例:

class Lock{
    public int l=0;
}

class Numbers extends Thread
{
    final Lock lock;
    Numbers(Lock l,String name){
        super(name);
        lock=l;
    }

    public void run() {
        synchronized(lock) {
            for(int i=0;i<100;i++){
                if(i==50){
                    try {
                        while(lock.l==0){
                            System.out.println("Waiting for letters to complete");
                            lock.wait();
                            System.out.println("Wait complete");
                        }
                    }
                    catch(InterruptedException e){
                        System.err.println("ERROR");
                    }
                }
                System.out.println(i);
            }
        }
    }
}

class Letters extends Thread {
    final Lock lock;
    Letters(Lock l,String name)
    {
        super(name);
        lock=l;
    }

    public void run()
    {
        synchronized(lock){
            for(int i=65;i<=90;i++)
                System.out.println((char)i);
            lock.l=1;
            lock.notify();
        }
    }
}

class MyClass {
    public static void main(String args[]) {
        Lock l=new Lock();
        Numbers n=new Numbers(l,"Numbers");
        Letters let=new Letters(l,"Letters");
        n.start();
        let.start();
    }
}
相关问题