Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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.lang.IllegalMonitorStateException:(m=null)无法获取的监视器_Java_Multithreading_Locking_Pool - Fatal编程技术网

java.lang.IllegalMonitorStateException:(m=null)无法获取的监视器

java.lang.IllegalMonitorStateException:(m=null)无法获取的监视器,java,multithreading,locking,pool,Java,Multithreading,Locking,Pool,为什么会发生这种情况?问题是monitor对象肯定不是空的,但我们仍然经常遇到这种异常: java.lang.IllegalMonitorStateException: (m=null) Failed to get monitor for (tIdx=60) at java.lang.Object.wait(Object.java:474) at ... 引发此问题的代码是一个简单的池解决方案: public Object takeObject() {

为什么会发生这种情况?问题是monitor对象肯定不是空的,但我们仍然经常遇到这种异常:

java.lang.IllegalMonitorStateException: (m=null) Failed to get monitor for (tIdx=60)
        at java.lang.Object.wait(Object.java:474)
        at ...
引发此问题的代码是一个简单的池解决方案:

    public Object takeObject() {
        Object obj = internalTakeObject();
        while (obj == null) {
            try {
                available.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            obj = internalTakeObject();
        }
        return obj;
    }

    private Object internalTakeObject() {
        Object obj = null;
        synchronized (available) {
            if (available.size() > 0) {
                obj = available.keySet().iterator().next();
                available.remove(obj);
                synchronized (taken) {
                    taken.put(obj, Boolean.valueOf(true));
                }
            }
        }
        return obj;
    }

    public void returnObject(Object obj) {
        synchronized (taken) {
            taken.remove(obj);
        }
        synchronized (available) {
            if (available.size() < size) {
                available.put(obj, Boolean.valueOf(true));
                available.notify();
            }
        }
    }
公共对象takeObject(){
Object obj=internalTakeObject();
while(obj==null){
试一试{
可用。等待();
}捕捉(中断异常e){
抛出新的运行时异常(e);
}
obj=内部TakeObject();
}
返回obj;
}
私有对象internalTakeObject(){
objectobj=null;
已同步(可用){
如果(可用。大小()>0){
obj=available.keySet().iterator().next();
可用。移除(obj);
已同步(已拍摄){
take.put(obj,Boolean.valueOf(true));
}
}
}
返回obj;
}
公共对象(对象obj){
已同步(已拍摄){
采取。移除(obj);
}
已同步(可用){
如果(可用。size()
我错过什么了吗


EDIT:异常发生在
available.wait()中行。

可用。等待()必须在同步(可用)部分中

请参阅javadoc for Object.wait

特别是“当前线程必须拥有此对象的监视器。”和“[抛出]IllegalMonitorStateException-如果当前线程不是对象监视器的所有者。”也就是说,您需要在要调用的对象上同步等待

因此,您的代码应该是:

synchronized (available) {
    available.wait();
}
takeObject()方法必须是同步的,或者,我们必须在该方法中写入同步块。我希望您应该为此获得编译时异常。

您从

因为调用wait()方法的当前线程不是 由“可用”对象引用引用

要使线程成为对象监视器的所有者,有3种方法

  • 通过执行该对象的同步实例方法
  • 通过执行在对象上同步的同步块的主体
  • 对于类类型的对象,执行该类的同步静态方法
  • 每个场景的简单示例代码。对于每种类型,所有三个代码段都是独立的类,只需复制代码并运行它即可。我在代码中添加了大量注释,以解释每种情况下发生的情况。如果对你来说评论太多。只需删除它们,使代码更简洁

    另外,首先阅读main()方法中的代码,了解threadOne和threadTwo

  • 通过执行该对象的同步实例方法

    import static java.lang.System.out;
    
    public class SynchronizedInstanceMethodClass {
    
        synchronized void synchronizedInstanceMethod() { // threadOne acquire the monitor for "this" and continue.
    
                try {
    
                    out.println("EVENT #1 threadOne is about to strat waiting on the "
                            +"monitor it already has - [\"this\"]....");
    
                    this.wait(); // The threadOne already have the monitor for "this", 
                                //  just release the monitor and go and wait threadOne.
    
                    out.println("EVENT #3 Notify received and continue execution...");
    
                } catch (InterruptedException interruptedException) {
                    interruptedException.printStackTrace();
                }
        }
    
    
        synchronized void notifierForAllThreads() { // threadTwo acquire the monitor for "this", 
                                                   // which was released by threadOne when it went to waiting and contine.
    
                out.println("EVENT #2 threadTwo is about to notify all threads(including threadOne) "
                        +"   waiting on the monitor of -[\"this\"]....");
    
                this.notifyAll(); // threadTwo who owns the monitor on "this" notifies all 
                                 // threads waiting on "this" and releases the monitor
        }
    
        public static void main(String [] args) {
    
            SynchronizedInstanceMethodClass mc  = new SynchronizedInstanceMethodClass();
            Thread threadOne = new Thread(() -> {mc.synchronizedInstanceMethod();});
            Thread threadTwo = new Thread(() -> {mc.notifierForAllThreads();});
    
            threadOne.start(); // Start the waiting of Thread one
            threadTwo.start(); // Notify the waiting threadOne
        }
    
    }
    
  • 通过执行在对象上同步的同步块的主体

    import static java.lang.System.out;
    
    public class SynchronizedBlockClass {
    
        void synchronizedBlockInstanceMethod() {
    
            synchronized (this) { // threadOne acquire the monitor for "this" and continue.
    
                try {
    
                    out.println("EVENT #1 threadOne is about to strat waiting on the "
                                +"monitor it already has - [\"this\"]....");
    
                    this.wait(); // The threadOne already have the monitor for "this", 
                                //  just release the monitor and go and wait threadOne.
    
                    out.println("EVENT #3 Notify received and continue execution...");
                } catch (InterruptedException interruptedException) {
                    interruptedException.printStackTrace();
                }
            }
        }
    
    
        void synchronizedBlockNotifierForAllThreads() {
    
            synchronized (this) { // threadTwo acquire the monitor for "this", 
                                 // which was released by threadOne when it went to waiting and continue.
    
                    out.println("EVENT #2 threadTwo is about to notify all threads(including threadOne) "
                            +"   waiting on the monitor of -[\"this\"]....");
    
                    this.notifyAll(); // threadTwo who owns the monitor on "this" notifies all 
                                     // threads waiting on "this" and releases the monitor
                }
        }
    
        public static void main(String [] args) {
            SynchronizedBlockClass mc  = new SynchronizedBlockClass();
            Thread threadOne = new Thread(() -> {mc.synchronizedBlockInstanceMethod();});
            Thread threadTwo = new Thread(() -> {mc.synchronizedBlockNotifierForAllThreads();});
    
            threadOne.start(); // Start the waiting of Thread one
            threadTwo.start(); // Notify the waiting threadOne
        }
    
    }
    
  • 对于类类型的对象,执行该类的同步静态方法

    import static java.lang.System.out;
    
    public class StaticClassReferenceClass {
    
        void synchronizedBlockInstanceMethod() {
    
            synchronized (StaticClassReferenceClass.class) { // threadOne acquire the monitor for class literal and continue.
    
                try {
    
                    out.println("EVENT #1 threadOne is about to strat waiting on the "
                                +"monitor it already has - [StaticClassReferenceClass.class]....");
    
                    StaticClassReferenceClass.class.wait(); // The threadOne already have the monitor for the class literal, 
                                //  So it just release the monitor and go and wait.
    
                    out.println("EVENT #3 Notify received and continue execution...");
                } catch (InterruptedException interruptedException) {
                    interruptedException.printStackTrace();
                }
            }
        }
    
    
        void synchronizedBlockNotifierForAllThreads() {
    
            synchronized (StaticClassReferenceClass.class) { // threadTwo acquire the monitor for the class literal, 
                                 // which was released by threadOne when it went to waiting.
    
                    out.println("EVENT #2 threadTwo is about to notify all threads(including threadOne) "
                            +"   waiting on the monitor of -[StaticClassReferenceClass.class]....");
    
                    StaticClassReferenceClass.class.notifyAll(); // threadTwo who owns the monitor on the class literal notifies all 
                                     // threads waiting on it and releases the monitor
                }
        }
    
        public static void main(String [] args) {
            StaticClassReferenceClass mc  = new StaticClassReferenceClass();
            Thread threadOne = new Thread(() -> {mc.synchronizedBlockInstanceMethod();});
            Thread threadTwo = new Thread(() -> {mc.synchronizedBlockNotifierForAllThreads();});
    
            threadOne.start(); // Start the waiting of Thread one
            threadTwo.start(); // Notify the waiting threadOne
        }
    
    }
    

  • 您能告诉我们源代码中474是哪一行吗?异常发生在available.wait()中;行,但第474行来自java.lang.Object类。值得知道的是:如果此异常发生在
    available.notify()
    上,请使用相同的模式。我尝试使用同步函数而不是块来执行相同的操作,但它抛出了IllegalMonitorStateException。这是为什么呢?Hunter,当你同步一个成员函数时,你正在锁定这个对象,所以
    this.wait()
    应该可以工作。您到底做了什么?同步方法确实与
    this.wait()
    相同,但它们拥有执行这些方法的对象的监视器,而不是
    可用的
    。所以这与
    同步(可用)
    import static java.lang.System.out;
    
    public class StaticClassReferenceClass {
    
        void synchronizedBlockInstanceMethod() {
    
            synchronized (StaticClassReferenceClass.class) { // threadOne acquire the monitor for class literal and continue.
    
                try {
    
                    out.println("EVENT #1 threadOne is about to strat waiting on the "
                                +"monitor it already has - [StaticClassReferenceClass.class]....");
    
                    StaticClassReferenceClass.class.wait(); // The threadOne already have the monitor for the class literal, 
                                //  So it just release the monitor and go and wait.
    
                    out.println("EVENT #3 Notify received and continue execution...");
                } catch (InterruptedException interruptedException) {
                    interruptedException.printStackTrace();
                }
            }
        }
    
    
        void synchronizedBlockNotifierForAllThreads() {
    
            synchronized (StaticClassReferenceClass.class) { // threadTwo acquire the monitor for the class literal, 
                                 // which was released by threadOne when it went to waiting.
    
                    out.println("EVENT #2 threadTwo is about to notify all threads(including threadOne) "
                            +"   waiting on the monitor of -[StaticClassReferenceClass.class]....");
    
                    StaticClassReferenceClass.class.notifyAll(); // threadTwo who owns the monitor on the class literal notifies all 
                                     // threads waiting on it and releases the monitor
                }
        }
    
        public static void main(String [] args) {
            StaticClassReferenceClass mc  = new StaticClassReferenceClass();
            Thread threadOne = new Thread(() -> {mc.synchronizedBlockInstanceMethod();});
            Thread threadTwo = new Thread(() -> {mc.synchronizedBlockNotifierForAllThreads();});
    
            threadOne.start(); // Start the waiting of Thread one
            threadTwo.start(); // Notify the waiting threadOne
        }
    
    }