1
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 的数字后抛出异常,然后打印 AZ,然后无法执行显示 IllegalMonitorStateException

4

1 回答 1

4

无法执行显示 IllegalMonitorStateException。

notify();这是由于对方法的调用不遵守其合同的事实:

唤醒正在此对象的监视器上等待的单个线程。 (...) 此方法只能由作为该对象监视器所有者的线程调用。

这同样适用于该wait方法:

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

TL:博士

您正在调用错误的wait实例的隐式锁return by )。notify()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();
    }
}
于 2021-02-10T07:36:40.203 回答