java.lang.IllegalMonitorStateException: (m=null) Failed to get monitor for

87,948

Solution 1

See the javadoc for Object.wait.

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.

so your code should be:

synchronized (available) {
    available.wait();
}

Solution 2

available.wait(); must be in a synchronized(available) section

Solution 3

You are getting the "IllegalMonitorStateException" from

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.

For a thread to become the owner of an object's monitor, there are 3 ways.

  1. By executing a synchronized instance method of that object.
  2. By executing the body of a synchronized block that synchronizes on the object.
  3. For objects of type Class by executing a synchronized static method of that 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.

  1. 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
        }
    
    }
    
  2. 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
        }
    
    }
    
  3. 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
        }
    
    }
    
Share:
87,948
Andrey Adamovich
Author by

Andrey Adamovich

A software craftsman with many years of experience in different lifecycle phases of software creation. He is passionate about defining good development practices, documenting and presenting architecture, reuse of code and design patterns, profiling and analysis of application performance as well as extreme automation of development and operations activities. At the moment, Andrey is working as a free-lance DevOps consultant offering his expertise in implementing DevOps initiatives, selecting automation tooling, switching to infrastructure-as-code and immutable infrastructure and constructing software delivery pipelines. Another Andrey's passion is teaching software automation practices and tooling. His DevOps MasterClass (eXtreme Automation) course has been delivered more than 20 times in various locations in Europe: Austria, Sweden, Denmark, UK, Romania, Estonia, Latvia. Andrey is also a co-founder of DevChampions training center. Andrey is a frequent speaker at international conferences and local communities. He is one of the leaders of LatCraft - Latvian Software Craftsmanship Community as well as co-founder and organizer of DevTernity conference.

Updated on February 03, 2020

Comments

  • Andrey Adamovich
    Andrey Adamovich over 4 years

    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.

  • Andreas Dolk
    Andreas Dolk over 11 years
    Worth to know: Use the same pattern if this exception occurs on available.notify().
  • Hunter S
    Hunter S over 8 years
    I tried using a synchronized function instead of a block to do the same thing, but it threw the IllegalMonitorStateException. Why is that?
  • tgdavies
    tgdavies over 8 years
    Hunter, when you make a member function synchronized you are taking a lock on the object -- so this.wait() should work. What exactly did you do?
  • Rhubarb
    Rhubarb almost 8 years
    a synchronized method is indeed the same as this.wait(), but those own the monitor of the object in which these methods are executing, not available. So that's not the same as synchronized(available)