3

The below program is supposed to print even and odd numbers by two different threads but I am getting illegal monitor exception on notify method in the below code :

public class oddeven {
    static volatile Integer t = 0;

    public static void main(String as[]) {
        oddrunnable or = new oddrunnable(t);
        evenrunnable er = new evenrunnable(t);

        Thread t1 = new Thread(or, "odd");
        Thread t2 = new Thread(er, "even");

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

    }

}

class oddrunnable implements Runnable {
    Integer t;

    public oddrunnable(Integer t) {
        this.t = t;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub

        synchronized (t) {
            while (true) {

                if (t % 2 == 0) {
                    try {
                        t.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                System.out.println("Current thread id " + Thread.currentThread().getName());
                t++;
                t.notify();
            }
        }
    }

}

class evenrunnable implements Runnable {
    Integer t;

    public evenrunnable(Integer t) {
        this.t = t;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub

        // TODO Auto-generated method stub

        synchronized (t) {
            while (true) {

                if (t % 2 != 0) {
                    try {
                        t.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                System.out.println("Current thread id " + Thread.currentThread().getName());
                t++;
                t.notify(); // <-------------------exception on this line
            }
        }

    }

}

the notify method is called on the synchronized object itself. Not sure why this is coming :

    Current thread id even
Exception in thread "even" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at evenrunnable.run(oddeven.java:86)
    at java.lang.Thread.run(Thread.java:619)
Bilbo Baggins
  • 2,899
  • 10
  • 52
  • 77
jayendra bhatt
  • 1,337
  • 2
  • 19
  • 41
  • http://stackoverflow.com/questions/25733718/illegalmonitorstateexception-on-notify similar question. accepted answer explains it well. – WannaBeCoder Dec 23 '15 at 12:37

2 Answers2

6

Integers in java wrapper are immutable, so as soon as you do t++, you are going to assign a new Integer object which you didn't took lock against and hence you get IllegalMonitorStateException.

Instead of Integer, use AtomicInteger and then use incrementAndGet api to increment the value of counter.

SMA
  • 36,381
  • 8
  • 49
  • 73
1

The problem is in using Integer object for synchronization and than doing increment(++) operation on it. I think its creating new integer object and than all the synchronized logic is going for toss. I am not sure about it as while debugging your code, eclipse was not showing whether it created new object.

A better alternative is to use some wrapper object around your integer or AtomicInteger class. Here is your code with AtomicInteger class used

public class oddeven {
    static volatile AtomicInteger t = new AtomicInteger(0);

    public static void main(String as[]) {
        oddrunnable or = new oddrunnable(t);
        evenrunnable er = new evenrunnable(t);

        Thread t1 = new Thread(or, "odd");
        Thread t2 = new Thread(er, "even");

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

    }

}

class oddrunnable implements Runnable {
    AtomicInteger t;

    public oddrunnable(AtomicInteger t) {
        this.t = t;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub

        synchronized (t) {
            while (true) {

                if (t.intValue() % 2 == 0) {
                    try {
                        t.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                System.out.println("Current thread id " + Thread.currentThread().getName());
                t.incrementAndGet();
                t.notify();
            }
        }
    }

}

class evenrunnable implements Runnable {
    AtomicInteger t;

    public evenrunnable(AtomicInteger t) {
        this.t = t;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub

        // TODO Auto-generated method stub

        synchronized (t) {
            while (true) {

                if (t.intValue() % 2 != 0) {
                    try {
                        t.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                System.out.println("Current thread id " + Thread.currentThread().getName());
                t.incrementAndGet();

                t.notify(); // <-------------------exception on this line
            }
        }

    }

}
Harbeer Kadian
  • 364
  • 2
  • 14