How to use wait and notify in Java without IllegalMonitorStateException?

JavaMultithreadingExceptionJava Threads

Java Problem Overview


I have 2 matrices and I need to multiply them and then print the results of each cell. As soon as one cell is ready I need to print it, but for example I need to print the [0][0] cell before cell [2][0] even if the result of [2][0] is ready first. So I need to print it by order. So my idea is to make the printer thread wait until the multiplyThread notifies it that the correct cell is ready to be printed and then the printerThread will print the cell and go back to waiting and so on..

So I have this thread that does the multiplication:

public void run() 
{
	int countNumOfActions = 0; // How many multiplications have we done
	int maxActions = randomize(); // Maximum number of actions allowed
	
	for (int i = 0; i < size; i++)
	{		
		result[rowNum][colNum] = result[rowNum][colNum] + row[i] * col[i];
		countNumOfActions++;
		// Reached the number of allowed actions
		if (countNumOfActions >= maxActions)
		{
			countNumOfActions = 0;
			maxActions = randomize();
			yield();
		}	
	}
	isFinished[rowNum][colNum] = true;
	notify();
}

Thread that prints the result of each cell:

public void run()
{
	int j = 0; // Columns counter
	int i = 0; // Rows counter
	System.out.println("The result matrix of the multiplication is:");
	
	while (i < creator.getmThreads().length)
	{
		synchronized (this)
		{
			try 
			{
				this.wait();
			} 
			catch (InterruptedException e1) 
			{
			}
		}
		if (creator.getmThreads()[i][j].getIsFinished()[i][j] == true)
		{
			if (j < creator.getmThreads()[i].length)
			{
				System.out.print(creator.getResult()[i][j] + " ");
				j++;
			}
			else
			{
				System.out.println();
				j = 0;
				i++;
				System.out.print(creator.getResult()[i][j] + " ");
			}
		}
	}

Now it throws me these exceptions:

Exception in thread "Thread-9" java.lang.IllegalMonitorStateException
	at java.lang.Object.notify(Native Method)
	at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-6" Exception in thread "Thread-4" java.lang.IllegalMonitorStateException
	at java.lang.Object.notify(Native Method)
	at multiplyThread.run(multiplyThread.java:49)
java.lang.IllegalMonitorStateException
	at java.lang.Object.notify(Native Method)
	at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-5" java.lang.IllegalMonitorStateException
	at java.lang.Object.notify(Native Method)
	at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-8" java.lang.IllegalMonitorStateException
	at java.lang.Object.notify(Native Method)
	at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-7" java.lang.IllegalMonitorStateException
	at java.lang.Object.notify(Native Method)
	at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-11" java.lang.IllegalMonitorStateException
	at java.lang.Object.notify(Native Method)
	at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-10" java.lang.IllegalMonitorStateException
	at java.lang.Object.notify(Native Method)
	at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-12" java.lang.IllegalMonitorStateException
	at java.lang.Object.notify(Native Method)
	at multiplyThread.run(multiplyThread.java:49)

line 49 in multiplyThread is the "notify()"..I think I need to use the synchronized differently but I am not sure how.

If anyone can help this code to work I will really appreciate it.

Java Solutions


Solution 1 - Java

To be able to call notify() you need to synchronize on the same object.

synchronized (someObject) {
    someObject.wait();
}

/* different thread / object */
synchronized (someObject) {
    someObject.notify();
}

Solution 2 - Java

While using the wait and notify or notifyAll methods in Java the following things must be remembered:

  1. Use notifyAll instead of notify if you expect that more than one thread will be waiting for a lock.
  2. The wait and notify methods must be called in a synchronized context. See the link for a more detailed explanation.
  3. Always call the wait() method in a loop because if multiple threads are waiting for a lock and one of them got the lock and reset the condition, then the other threads need to check the condition after they wake up to see whether they need to wait again or can start processing.
  4. Use the same object for calling wait() and notify() method; every object has its own lock so calling wait() on object A and notify() on object B will not make any sense.

Solution 3 - Java

Do you need to thread this at all ? I'm wondering how big your matrices are, and whether there's any benefit in having one thread print whilst the other does the multiplication.

Perhaps it would be worth measuring this time before doing the relatively complex threading work ?

If you do need to thread it, I would create 'n' threads to perform the multiplication of the cells (perhaps 'n' is the number of cores available to you), and then use the ExecutorService and Future mechanism to dispatch multiple multiplications simultaneously.

That way you can optimise the work based on the number of cores, and you're using the higher level Java threading tools (which should make life easier). Write the results back into a receiving matrix, and then simply print this once all your Future tasks have completed.

Solution 4 - Java

Let's say you have 'black box' application with some class named BlackBoxClass that has method doSomething();.

Further, you have observer or listener named onResponse(String resp) that will be called by BlackBoxClass after unknown time.

The flow is simple:

private String mResponse = null; 
 ...
BlackBoxClass bbc = new BlackBoxClass();
   bbc.doSomething();
...
@override
public void onResponse(String resp){        
      mResponse = resp;       
}

Lets say we don't know what is going on with BlackBoxClass and when we should get answer but you don't want to continue your code till you get answer or in other word get onResponse call. Here enters 'Synchronize helper':

public class SyncronizeObj {
public void doWait(long l){
	synchronized(this){
		try {
			this.wait(l);
		} catch(InterruptedException e) {
		}
	}
}

public void doNotify() {
	synchronized(this) {
		this.notify();
	}
}

public void doWait() {
	synchronized(this){
		try {
			this.wait();
		} catch(InterruptedException e) {
		}
	}
}
}

Now we can implement what we want:

public class Demo {

private String mResponse = null; 
 ...
SyncronizeObj sync = new SyncronizeObj();

public void impl(){

BlackBoxClass bbc = new BlackBoxClass();
   bbc.doSomething();

   if(mResponse == null){
      sync.doWait();
    }

/** at this momoent you sure that you got response from  BlackBoxClass because
  onResponse method released your 'wait'. In other cases if you don't want wait too      
  long (for example wait data from socket) you can use doWait(time) 
*/ 
...

}


@override
public void onResponse(String resp){        
      mResponse = resp;
      sync.doNotify();       
   }

}

Solution 5 - Java

You can only call notify on objects where you own their monitor. So you need something like

synchronized(threadObject)
{
   threadObject.notify();
}

Solution 6 - Java

notify() needs to be synchronized as well

Solution 7 - Java

I'll right simple example show you the right way to use wait and notify in Java. So I'll create two class named ThreadA & ThreadB. ThreadA will call ThreadB.

public class ThreadA {
    public static void main(String[] args){
        ThreadB b = new ThreadB();//<----Create Instance for seconde class
        b.start();//<--------------------Launch thread
 
        synchronized(b){
            try{
                System.out.println("Waiting for b to complete...");
                b.wait();//<-------------WAIT until the finish thread for class B finish
            }catch(InterruptedException e){
                e.printStackTrace();
            }
 
            System.out.println("Total is: " + b.total);
        }
    }
} 

and for Class ThreadB:

class ThreadB extends Thread{
    int total;
    @Override
    public void run(){
        synchronized(this){
            for(int i=0; i<100 ; i++){
                total += i;
            }
            notify();//<----------------Notify the class wich wait until my    finish 
//and tell that I'm finish
            }
        }
    }

Solution 8 - Java

Simple use if you want How to execute threads alternatively :-

public class MyThread {
    public static void main(String[] args) {
        final Object lock = new Object();
        new Thread(() -> {
            try {
                synchronized (lock) {
                    for (int i = 0; i <= 5; i++) {
                        System.out.println(Thread.currentThread().getName() + ":" + "A");
                        lock.notify();
                        lock.wait();
                    }
                }
            } catch (Exception e) {}
        }, "T1").start();

        new Thread(() -> {
            try {
                synchronized (lock) {
                    for (int i = 0; i <= 5; i++) {
                        System.out.println(Thread.currentThread().getName() + ":" + "B");
                        lock.notify();
                        lock.wait();
                    }
                }
            } catch (Exception e) {}
        }, "T2").start();
    }
}

> response :-

T1:A
T2:B
T1:A
T2:B
T1:A
T2:B
T1:A
T2:B
T1:A
T2:B
T1:A
T2:B

Solution 9 - Java

we can call notify to resume the execution of waiting objects as

public synchronized void guardedJoy() {
    // This guard only loops once for each special event, which may not
    // be the event we're waiting for.
    while(!joy) {
        try {
            wait();
        } catch (InterruptedException e) {}
    }
    System.out.println("Joy and efficiency have been achieved!");
}

resume this by invoking notify on another object of same class

public synchronized notifyJoy() {
    joy = true;
    notifyAll();
}

Solution 10 - Java

For this particular problem, why not store up your various results in variables and then when the last of your thread is processed you can print in whatever format you want. This is especially useful if you are gonna be using your work history in other projects.

Solution 11 - Java

This looks like a situation for producer-consumer pattern. If you’re using java 5 or up, you may consider using blocking queue(java.util.concurrent.BlockingQueue) and leave the thread coordination work to the underlying framework/api implementation. See the example from java 5: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html or java 7 (same example): http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html

Solution 12 - Java

You have properly guarded your code block when you call wait() method by using synchronized(this).

But you have not taken same precaution when you call notify() method without using guarded block : synchronized(this) or synchronized(someObject)

If you refer to oracle documentation page on Object class, which contains wait() ,notify(), notifyAll() methods, you can see below precaution in all these three methods

> This method should only be called by a thread that is the owner of this object's monitor

Many things have been changed in last 7 years and let's have look into other alternatives to synchronized in below SE questions:

https://stackoverflow.com/questions/11821801/why-use-a-reentrantlock-if-one-can-use-synchronizedthis/36827191#36827191

https://stackoverflow.com/questions/4201713/synchronization-vs-lock/34267717#34267717

https://stackoverflow.com/questions/442564/avoid-synchronizedthis-in-java/36692190#36692190

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGregView Question on Stackoverflow
Solution 1 - JavaBombeView Answer on Stackoverflow
Solution 2 - JavaJackobView Answer on Stackoverflow
Solution 3 - JavaBrian AgnewView Answer on Stackoverflow
Solution 4 - JavaMaxim ShoustinView Answer on Stackoverflow
Solution 5 - JavaPaulJWilliamsView Answer on Stackoverflow
Solution 6 - Javatakete.dkView Answer on Stackoverflow
Solution 7 - JavaBERGUIGA Mohamed AmineView Answer on Stackoverflow
Solution 8 - JavaVijayView Answer on Stackoverflow
Solution 9 - JavaGreesh KumarView Answer on Stackoverflow
Solution 10 - JavakbluueView Answer on Stackoverflow
Solution 11 - Javauser3044236View Answer on Stackoverflow
Solution 12 - JavaRavindra babuView Answer on Stackoverflow