java.lang.IllegalMonitorStateException: (m=null) 无法获得监控
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1553886/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
java.lang.IllegalMonitorStateException: (m=null) Failed to get monitor for
提问by Andrey Adamovich
Why may this happen? The thing is that monitor object is not null for sure, but still we get this exception quite often:
为什么会发生这种情况?问题是监视器对象肯定不是空的,但我们仍然经常遇到这个异常:
java.lang.IllegalMonitorStateException: (m=null) Failed to get monitor for (tIdx=60)
at java.lang.Object.wait(Object.java:474)
at ...
The code that provokes this is a simple pool solution:
引发此问题的代码是一个简单的池解决方案:
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();
}
}
}
Am I missing something?
我错过了什么吗?
EDIT: The exception happens in available.wait();
line.
编辑:异常发生在available.wait();
队列中。
采纳答案by tgdavies
See the javadoc for Object.wait.
请参阅 Object.wait 的 javadoc。
in particular "The current thread must own this object's monitor." and "[throws] IllegalMonitorStateException - if the current thread is not the owner of the object's monitor." That is, you need to synchronize on the object you are going to call wait on.
特别是“当前线程必须拥有此对象的监视器。” 和“[抛出] IllegalMonitorStateException - 如果当前线程不是对象监视器的所有者。” 也就是说,您需要在要调用 wait 的对象上进行同步。
so your code should be:
所以你的代码应该是:
synchronized (available) {
available.wait();
}
回答by Maurice Perry
available.wait();
must be in a synchronized(available) section
available.wait();
必须在同步(可用)部分
回答by prasad
takeObject() method must be synchronized or, we have to write synchronized block inside this method. I hope u should get compile time exception for this.
takeObject() 方法必须是同步的,否则我们必须在这个方法中写入同步块。我希望你应该为此获得编译时异常。
回答by Jeewantha Samaraweera
You are getting the "IllegalMonitorStateException" from
你从“IllegalMonitorStateException”得到
available.wait()
because the current thread that invokes the wait() method is not the owner of the Object's monitor that is referenced by the "available" object reference.
因为调用 wait() 方法的当前线程不是“可用”对象引用所引用的对象监视器的所有者。
For a thread to become the owner of an object's monitor, there are 3 ways.
要让线程成为对象监视器的所有者,有 3 种方法。
- By executing a synchronized instance method of that object.
- By executing the body of a synchronized block that synchronizes on the object.
- For objects of type Class by executing a synchronized static method of that class.
- 通过执行该对象的同步实例方法。
- 通过执行在对象上同步的同步块的主体。
- 对于 Class 类型的对象,通过执行该类的同步静态方法。
Simple sample code for each scenario. All three code snippets are separate classes for each type, just copy the code and run it. I added comments heavily into the code to explain what's happening in each case. If it's too many comments for you. just delete them to make the code more concise.
每个场景的简单示例代码。所有三个代码片段都是每种类型的单独类,只需复制代码并运行它。我在代码中添加了大量注释以解释每种情况下发生的情况。如果你的评论太多。只需删除它们以使代码更简洁。
Also, read the code in main() method first to get an idea about threadOne and threadTwo first.
另外,请先阅读 main() 方法中的代码,以先了解 threadOne 和 threadTwo。
By executing a synchronized instance method of that object.
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 } }
By executing the body of a synchronized block that synchronizes on the object.
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 } }
For objects of type Class by executing a synchronized static method of that class.
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 } }
通过执行该对象的同步实例方法。
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 } }
对于 Class 类型的对象,通过执行该类的同步静态方法。
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 } }