Home > Multithreading > Java Multithreading – Notify & Wait

Java Multithreading – Notify & Wait


Read about synchronization first to understand this article better.

notify() or notifyAll(), and wait() must be in a synchronized block for the object you are waiting on. So the following codes are correct;

public synchronized void method(){
	wait(); //or this.wait();
}

public void method(){
	synchronized(this){
		wait(); //or this.wait();
	}
}

public void method(){
	synchronized(a){
		a.wait();
	}
}

public synchronized void method(){
	synchronized(a){
		wait();
	}
}

But following code generates run time exception java.lang.IllegalMonitorStateException

public void method(){
	synchronized(a){
		wait();
	}
}

public void method(){
	synchronized(a){
		synchronized(this){
			wait(n);
		}
	}
}

public synchronized void method(){
	synchronized(a){
		wait(n);
	}
}

If you change synchronized object inside synchronized block notify() or notifyAll(), and wait() will give run time exception java.lang.IllegalMonitorStateException.

synchronized(a){
	a = 55;
	a.wait();
}

In above example, you are waiting on new copy of a while synchronizing on old copy of a. Below code doesn’t generate exception.

synchronized(a){
	a.wait();
	a = 55;
}

Because you are waiting on same copy of a, you are synchronizing on. Then you are changing a.

Thread.sleep(1000) asks current thread to wait till specified period. It doesn’t bother about locks and all. So it doesn’t releases lock. On the other hand, wait() releases lock and acquires lock again once notify() or notifyAll() get called on same object or specified time is over.

public void acquire(){
	synchronized(a){
		print("acquire()");
		try{
			a.wait(5000);
			print("I have awoken");
			print(":" + a);
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	print("Leaving acquire()");
}

public void modify(int n){
	print("Entered in modify");
	synchronized(a){
		try{
			a.wait(3000);
			this.a=n;
			print("new value " + a);
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}

Output:
2012-03-06 19:51:27.969 :: A: acquire()
2012-03-06 19:51:27.969 :: B: Entered in modify
2012-03-06 19:51:32.992 :: B: new value 97
2012-03-06 19:51:32.992 :: A: I have awoken
2012-03-06 19:51:32.992 :: A: 97
2012-03-06 19:51:32.992 :: A: Leaving acquire()

Explanation:

Thread A: enters into monitor of a.
Thread B: waits to get entered into monitor of a.
Thread A: meets to a.wait(5000). So it releases lock on a.
Thread B: enters into monitor a. waits and acquires lock on a.
Thread A: try to acquire released lock. But it is already acquired by Thread B. So it waits.
Thread B: changes value of a.
Thread A: acquire lock on a. It prints new value of a.
On the other hand, if I use Thread.sleep(n) in place of wait(n)

public void acquire(){
	synchronized(a){
		print("acquire()");
		try{
			//a.wait(5000);
			Thread.sleep(5000);
			print("I have awoken");
			print(":" + a);
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	print("Leaving acquire()");
}

Output:
2012-03-06 20:02:39.395 :: A: acquire()
2012-03-06 20:02:39.395 :: B: Entered in modify
2012-03-06 20:02:44.418 :: A: I have awoken
2012-03-06 20:02:44.418 :: A: 10
2012-03-06 20:02:44.418 :: A: Leaving acquire()
2012-03-06 20:02:49.427 :: B: new value 97

Explanation:
When Thread A meets to sleep(n) it doesn’t release lock.

The problem with calling wait() and notify() on the empty string, or any other constant string is, that the JVM/Compiler internally translates constant strings into the same object. That means, that even if you have two different MyWaitNotify instances, they both reference the same empty string instance. This also means that threads calling wait() on the first MyWaitNotify instance risk being awakened by notify() calls on the second MyWaitNotify instance.
If there are multiple threads waiting on same object, notify() can awake any thread randomly. It arises the condition that some threads never get awaken and some always get awaken. This situation is called Starvation. Sometimes some greedy threads don’t release resources (call sleep() instead of wait() etc). It also force other threads to wait. Some threads increase their priority to get served first to CPU, it also force low priority threads to wait for long. These all conditions where any thread need to wait very long is called Starvation.

 

Advertisements
Categories: Multithreading
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: