如果我在同步块内使用wait,则会出现IllegalMonitorStateException的原因



我试图理解java核心同步。

我写了代码示例:

程序应写入

left右侧

10倍

package concurrency;
public class LeftRightWaitNotifyExample {
    final static String str = "1";
    public static void main(String[] args) {
        new LeftLegThread(str).start();
        new RightLegThread(str).start();
    }
}
class LeftLegThread extends Thread {
    String monitor;
    public LeftLegThread(String str) {
        monitor = str;
    }
    @Override
    public void run() {
        try {
            makeStep();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    private void makeStep() throws InterruptedException {
        synchronized (monitor) {
            for (int i = 0; i < 10; i++) {
                System.out.println("Left ");
                wait();
            }
        }
    }
}
class RightLegThread extends Thread {
    String monitor;
    public RightLegThread(String str) {
        monitor = str;
    }
    @Override
    public void run() {
        try {
            makeStep();
        } catch (InterruptedException e) {
        }
    }
    private void makeStep() throws InterruptedException {
        synchronized (monitor) {
            while (true) {
                System.out.println("Right ");
                notify();
                wait();
            }
        }
    }
}

我得到这个输出:

Left 
Right 
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:485)
    at concurrency.LeftLegThread.makeStep(LeftRightWaitNotifyExample.java:35)
    at concurrency.LeftLegThread.run(LeftRightWaitNotifyExample.java:23)
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at concurrency.RightLegThread.makeStep(LeftRightWaitNotifyExample.java:61)
    at concurrency.RightLegThread.run(LeftRightWaitNotifyExample.java:51)

在此之前,当我在synchronized块内使用wait方法时出现此错误。但在这里,我使用synchronized块内的等待

问题的原因是什么?如何解决?

更新

我根据建议重写代码:

public class LeftRightWaitNotifyExample {
    final static String str = "1";
    public static void main(String[] args) throws InterruptedException {
        new LeftLegThread(str).start();
        Thread.sleep(100);
        new RightLegThread(str).start();
    }
}
class LeftLegThread extends Thread {
    String monitor;
    public LeftLegThread(String str) {
        monitor = str;
    }
    @Override
    public void run() {
        try {
            makeStep();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    private void makeStep() throws InterruptedException {
        synchronized (monitor) {
            for (int i = 0; i < 2; i++) {
                System.out.println("Left ");
                monitor.wait();
                monitor.notify();
            }
        }
    }
}
class RightLegThread extends Thread {
    String monitor;
    public RightLegThread(String str) {
        monitor = str;
    }
    @Override
    public void run() {
        try {
            makeStep();
        } catch (InterruptedException e) {
        }
    }
    private void makeStep() throws InterruptedException {
        synchronized (monitor) {
            while (true) {
                System.out.println("Right ");
                monitor.notify();
                monitor.wait();
            }
        }
    }
}

电流输出:

Left 
Right 
Left 
Right 
Right 

为什么Right只出3而Left只出两次。为什么?

您在monitor上进行同步,因此也应该在监视器上进行wait()

monitor.wait();

现在您正在等待this,它不是监视器的所有者,因为同步在monitor上。

请注意,notify当然也应该在monitor对象上完成,并且您可能需要考虑在两个线程中使用notify/notifyAll。否则,可能会发生一个线程在等待丢失的通知。使用超时(wait的重载版本)也可能是捕捉角落案例的好主意。

原因-The current thread is not the owner of the object's monitor.若要调用wait()方法,当前线程必须拥有此对象的监视器
在您的情况下,您获得的是monitor对象上的监视器,而不是当前对象(此对象)。

您正试图锁定监视器对象。但它是锁定线程对象(LeftLegThread,RightLegThread)。实际上它并没有被同步锁定。

monitor.wait();将修复。

public class LeftRightWaitNotifyExample {
    final static String str = "1";
    public static void main(String[] args) throws InterruptedException {
        new LeftLegThread(str).start();
        Thread.sleep(1000);
        new RightLegThread(str).start();
    }
}
class LeftLegThread extends Thread {
    String monitor;
    public LeftLegThread(String str) {
        monitor = str;
    }
    @Override
    public void run() {
        try {
            makeStep();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    private void makeStep() throws InterruptedException {
        synchronized (monitor) {
            while (true) {
                System.out.println("Left ");
                monitor.wait();
                monitor.notify();
                Thread.sleep(1000);
            }
        }
    }
}
class RightLegThread extends Thread {
    String monitor;
    public RightLegThread(String str) {
        monitor = str;
    }
    @Override
    public void run() {
        try {
            makeStep();
        } catch (InterruptedException e) {
        }
    }
    private void makeStep() throws InterruptedException {
        synchronized (monitor) {
            while (true) {
                System.out.println("Right ");
                monitor.notify();
                monitor.wait();
                Thread.sleep(1000);
            }
        }
    }
}

相关内容

  • 没有找到相关文章

最新更新