Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting illegal monitor state exception on notify

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)
like image 499
jayendra bhatt Avatar asked Nov 21 '25 13:11

jayendra bhatt


2 Answers

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.

like image 107
SMA Avatar answered Nov 24 '25 01:11

SMA


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
            }
        }

    }

}
like image 36
Harbeer Kadian Avatar answered Nov 24 '25 02:11

Harbeer Kadian