2

Sometimes the below code throws IllegalStateMonitorException and sometimes it runs nicely. Not able to understand the scenarios how could it happen as it is always called under lock.lock().

Full Code:

public class OddEvenPrinter implements Runnable {
    private Lock lock = new ReentrantLock();
    Condition conditionFlag = lock.newCondition();
    private int counter = 0;

    public void run(){
        for(int i = 0; i<1000;i++){
            printEven();
            printOdd();
        }
    }

    private void printEven() {
        try{
            lock.lock();
            while(counter%2!=0){
                wait();
            }
            System.out.println(Thread.currentThread().getName()+" thread printing Even :"+counter);
            counter++;
            conditionFlag.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            lock.unlock();
        }
    }

    private void printOdd(){
        try{
            lock.lock();
            while(counter%2==0){
                wait();
            }
            System.out.println(Thread.currentThread().getName()+" thread printing Odd :"+counter);
            counter++;
            conditionFlag.signalAll();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        OddEvenPrinter counter = new OddEvenPrinter();
        Thread t1 = new Thread(counter);
        Thread t2 = new Thread(counter);
        t1.setName("First");
        t2.setName("Second");

        t1.start();
        t2.start();

        t1.join();
        t2.join();
    }
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
javaq
  • 131
  • 1
  • 9
  • 5
    You appear to be calling `wait()` without using a `synchronized` block. I'm surprised that *ever* works. – Jon Skeet Jun 18 '16 at 17:28
  • 1
    See this: http://stackoverflow.com/questions/14772236/illegal-monitor-state-exception and this: http://stackoverflow.com/questions/1537116/illegalmonitorstateexception-on-wait-call and this: http://stackoverflow.com/questions/7126550/java-wait-and-notify-illegalmonitorstateexception http://stackoverflow.com/questions/16758731/illegal-state-monitor-exception-in-distributed-system – krokodilko Jun 18 '16 at 17:30
  • 2
    I think you might be looking for Condition.await() https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/Condition.html#await-- – Brett Okken Jun 18 '16 at 17:31
  • Instead of synchronized, using reentrantLock and calling wait() only after calling lock() on reentrant lock. So ideally it should work. – javaq Jun 18 '16 at 17:32
  • ah..i got it. My bad :( – javaq Jun 18 '16 at 17:34
  • 2
    @javaq: But you're calling `wait` on the instance of `OddEvenCounter`, which you *don't* have the monitor for... that's entirely separate from the `Lock` you've created. I'm still trying to work out why it isn't throwing most of the time.. – Jon Skeet Jun 18 '16 at 17:34

0 Answers0