1

While running this I'm getting IllegalMonitorStateException because Even thread is trying to notify when it does not have lock on the object isEven. Why is this happening? A thread should only be able to go inside the synchronized block if it has lock on the object.

public class NumPrinter implements Runnable{

    public static Boolean isEven = true;
    private boolean isEvenThread;
    private int i;

    public void run() {
    while(i < 100){
     synchronized(isEven){
            boolean notPrinting = (isEven ^ isEvenThread);
            System.out.println(notPrinting);
            if(notPrinting) {
                try {
                    isEven.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }       
            System.out.print(i + ",");
            i = i+2;
            isEven = !isEven;
            isEven.notifyAll();
        }
     }
    }

    public NumPrinter(boolean isEvenThread) {

        this.isEvenThread = isEvenThread;   
        if(isEvenThread)
            i = 0;
        else 
            i = 1;
    }
}

public class MultiThreading {

    public static void main(String[] args) {

        Thread oddt = new Thread(new NumPrinter(false), "Odd");
        Thread event = new Thread(new NumPrinter(true), "Even");

        event.start();
        oddt.start();


    }
}
Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
Mayank
  • 11
  • 2
  • Seems that you are doing the same homework as [this guy](http://stackoverflow.com/q/33560337/4856258)... – Tagir Valeev Nov 12 '15 at 12:31
  • NOTE: The purpose of `synchronized` is _not_ to prevent two threads from executing the same code at the same time. Its purpose is to prevent two threads from accessing the same _data_ at the same time. – Solomon Slow Nov 12 '15 at 14:15

2 Answers2

2

It's likely that you need to synchronize/wait/notify on the constant object instead. Also declare the isEven as volatile. Finally, put wait() call in the loop checking the loop condition as official documentation recommends:

public class NumPrinter implements Runnable {
    private static final Object monitor = new Object();
    private static volatile boolean isEven = true;
    private final boolean isEvenThread;
    private int i;

    @Override
    public void run() {
        while (i < 100) {
            synchronized (monitor) {
                while (isEven ^ isEvenThread) {
                    try {
                        monitor.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.print(i + ",");
                i = i + 2;
                isEven = !isEven;
                monitor.notifyAll();
            }
        }
    }
    ...
}
Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
1

I'm not an expert in Java, but you rewrite the synchronization token here:

isEven = !isEven;

It may be not the only problem you have, but use another synchronization token at least (which isn't going to be rewritten).

Arthur Gevorkyan
  • 2,069
  • 1
  • 18
  • 31