Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/359.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么多个线程能够访问同步块?_Java_Multithreading_Synchronized_Illegalmonitorstateexcep - Fatal编程技术网

Java 为什么多个线程能够访问同步块?

Java 为什么多个线程能够访问同步块?,java,multithreading,synchronized,illegalmonitorstateexcep,Java,Multithreading,Synchronized,Illegalmonitorstateexcep,在运行此命令时,我得到了IllegalMonitorStateException,因为即使是线程也试图在对象上没有锁时发出通知isEven。为什么会这样?如果线程在对象上具有锁,那么它应该只能进入同步块内部 public class NumPrinter implements Runnable{ public static Boolean isEven = true; private boolean isEvenThread; private int i; p

在运行此命令时,我得到了
IllegalMonitorStateException
,因为即使是线程也试图在对象上没有锁时发出通知
isEven
。为什么会这样?如果线程在对象上具有锁,那么它应该只能进入同步块内部

public class NumPrinter implements Runnable{

    public static Boolean isEven = true;
    private boolean isEvenThread;
    private int i;

    public void run() {
    while(i < 100){
     synchronized(isEven){
            boolean notPrinting = (isEven ^ isEvenThread);
            System.out.println(notPrinting);
            if(notPrinting) {
                try {
                    isEven.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }       
            System.out.print(i + ",");
            i = i+2;
            isEven = !isEven;
            isEven.notifyAll();
        }
     }
    }

    public NumPrinter(boolean isEvenThread) {

        this.isEvenThread = isEvenThread;   
        if(isEvenThread)
            i = 0;
        else 
            i = 1;
    }
}

public class MultiThreading {

    public static void main(String[] args) {

        Thread oddt = new Thread(new NumPrinter(false), "Odd");
        Thread event = new Thread(new NumPrinter(true), "Even");

        event.start();
        oddt.start();


    }
}
公共类NumPrinter实现可运行{
公共静态布尔值isEven=true;
私有布尔线程;
私人互联网i;
公开募捐{
而(i<100){
已同步(isEven){
布尔notPrinting=(isEven^isEvenThread);
系统输出打印项次(不打印);
如果(不打印){
试一试{
等一等;
}捕捉(中断异常e){
e、 printStackTrace();
}
}       
系统输出打印(i+“,”);
i=i+2;
isEven=!isEven;
isEven.notifyAll();
}
}
}
公共NumPrinter(布尔isEvenThread){
this.isEvenThread=isEvenThread;
如果(IsEventThread)
i=0;
其他的
i=1;
}
}
公共类多线程{
公共静态void main(字符串[]args){
螺纹oddt=新螺纹(新NumPrinter(假),“奇数”);
线程事件=新线程(新NumPrinter(true),“偶数”);
event.start();
oddt.start();
}
}

我不是Java专家,但您可以在此处重写同步令牌:

我甚至=!伊塞文


这可能不是您遇到的唯一问题,但至少使用另一个同步令牌(不会被重写)。

您可能需要对常量对象进行同步/等待/通知。还将
isEven
声明为易失性。最后,将
wait()
调用放入循环,检查循环条件,作为正式文档:

公共类NumPrinter实现可运行{
私有静态最终对象监视器=新对象();
私有静态可变布尔值isEven=true;
私有最终布尔线程;
私人互联网i;
@凌驾
公开募捐{
而(i<100){
同步(监视器){
while(isEven^isEvenThread){
试一试{
monitor.wait();
}捕捉(中断异常e){
e、 printStackTrace();
}
}
系统输出打印(i+“,”);
i=i+2;
isEven=!isEven;
monitor.notifyAll();
}
}
}
...
}

似乎您正在做与…相同的作业注意:
同步的目的不是阻止两个线程同时执行相同的代码。它的目的是防止两个线程同时访问相同的数据。这是我试图说的扩展和精确版本。回答得好,伙计。
public class NumPrinter implements Runnable {
    private static final Object monitor = new Object();
    private static volatile boolean isEven = true;
    private final boolean isEvenThread;
    private int i;

    @Override
    public void run() {
        while (i < 100) {
            synchronized (monitor) {
                while (isEven ^ isEvenThread) {
                    try {
                        monitor.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.print(i + ",");
                i = i + 2;
                isEven = !isEven;
                monitor.notifyAll();
            }
        }
    }
    ...
}