Search code examples
javamultithreadingconditional-statementslockingnotify

Lock Condition.notify is throwing java.lang.IllegalMonitorStateException


I wrote a program to demonstrate Lock.Condition of java for multithreading purpose. I am getting IllegalMonitorStateException.

It is throwing an exception the below is output.

I am acquiring lock before calling notify on a condition. But still getting the below error. Can someone help. I googled a lot but couldn't find a solution.

Count : 0
lock java.util.concurrent.locks.ReentrantLock@4ce4d37e[Locked by thread Thread-0]
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException: current thread is not owner
at java.base/java.lang.Object.notify(Native Method)
at test.OddEvenPrinter.printEven(Test.java:51)
    at test.Test.lambda$main$1(Test.java:22)
at java.base/java.lang.Thread.run(Thread.java:1589)
Count : 1
lock java.util.concurrent.locks.ReentrantLock@4ce4d37e[Locked by thread Thread-1]
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException: current thread is not owner
    at java.base/java.lang.Object.notify(Native Method)
    at test.OddEvenPrinter.printOdd(Test.java:67)
    at test.Test.lambda$main$0(Test.java:14)
    at java.base/java.lang.Thread.run(Thread.java:1589)

The code for it is below:

package test;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Test {
    public static void main(String[] args) {
        final OddEvenPrinter oddEvenPrinter = new OddEvenPrinter();
        Runnable oddRunnable = () -> {
            try {
                while (true)
                    oddEvenPrinter.printOdd();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        Runnable evenRunnable = () -> {
            try {
                while (true)
                    oddEvenPrinter.printEven();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        new Thread(evenRunnable).start();
        new Thread(oddRunnable).start();
    }
}

class OddEvenPrinter {
    private final Lock lock = new ReentrantLock();
    private final Condition oddPrint = lock.newCondition();
    private final Condition evenPrint = lock.newCondition();
    private int count;
    public void printEven() throws InterruptedException {
        lock.lock();
        try {
            Thread.sleep(3000);
            while (count % 2 == 1) {
                evenPrint.await();
            }
            System.out.println("Count : " + count++);
            System.out.println("lock " + lock);
            oddPrint.notify();
        } finally {
            lock.unlock();
        }
    }
    public void printOdd() throws InterruptedException {
        lock.lock();
        try {
            Thread.sleep(2000);
            while (count % 2 == 0) {
                oddPrint.await();
            }
            System.out.println("Count : " + count++);
            System.out.println("lock " + lock);
            evenPrint.notify();
        } finally {
            lock.unlock();
        }
    }
}

Solution

  • I have used notify instead of using signal method when I am using lock conditions.

    I am pasting the corrected code.

    package test;
    
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class Test {
    
        public static void main(String[] args) {
            final OddEvenPrinter oddEvenPrinter = new OddEvenPrinter();
            Runnable oddRunnable = () -> {
                try {
                    while (true)
                        oddEvenPrinter.printOdd();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            };
            Runnable evenRunnable = () -> {
                try {
                    while (true)
                        oddEvenPrinter.printEven();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            };
            new Thread(evenRunnable).start();
            new Thread(oddRunnable).start();
        }
    }
    
    class OddEvenPrinter {
    
        private final Lock lock = new ReentrantLock();
    
        private final Condition oddPrint = lock.newCondition();
    
        private final Condition evenPrint = lock.newCondition();
    
        private int count;
    
        public void printEven() throws InterruptedException {
            lock.lock();
            try {
                Thread.sleep(3000);
                while (count % 2 == 1) {
                    evenPrint.await();
                }
                System.out.println("Count : " + count++);
                System.out.println("lock " + lock);
                oddPrint.signal();
            } finally {
                lock.unlock();
            }
    
        }
    
        public void printOdd() throws InterruptedException {
            lock.lock();
            try {
                Thread.sleep(2000);
                while (count % 2 == 0) {
                    oddPrint.await();
                }
                System.out.println("Count : " + count++);
                System.out.println("lock " + lock);
                evenPrint.signal();
            } finally {
                lock.unlock();
            }
    
        }
    }