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

gst*_*low 2 java concurrency synchronization wait

我尝试了解java核心同步.

我写了代码示例:

程序应该写

左右

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();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我得到这个输出:

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)
Run Code Online (Sandbox Code Playgroud)

在我waitsynchronized块内使用非方法时出现此错误之前.但在这里我使用内等待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();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

电流输出:

Left 
Right 
Left 
Right 
Right 
Run Code Online (Sandbox Code Playgroud)

为什么Right出局3但Left只有两次.为什么?

Seb*_*ian 5

你正在同步monitor,所以你也应该wait()在监视器上:

monitor.wait();
Run Code Online (Sandbox Code Playgroud)

现在你正在等待this,这不是监视器的所有者,因为同步已打开monitor.

请注意,当然notify也应该在monitor对象上完成,并且您可能要考虑在两个线程中使用notify/ .否则可能会发生一个线程饿死等待丢失通知.使用超时(重载版本)也可能是捕捉极端情况的好主意.notifyAllwait