Monday, December 14, 2009

Thread : Wait and Notify

Thread : Wait and Notify



We use sleep() method in Thread to pass the thread for some milliseconds/nanoseconds and resume the thread on its own. However, while waiting for the shared resource, this will not help.

In JAVA, Object class comes with wait() and notify/notifyAll methods, which helps us to mark saying, I am waiting for this object, who ever owns object monitor lock, release and let me know. While calling this methods, we have to own the object monitor lock of this





public class WaitNotifytest {
static Object obj=new Object();

public static void main(String[] args) throws Exception{
new Thread()
{
@Override
public void run() {
try
{
obj.wait();
}catch(Exception e)
{
e.printStackTrace();
}
}
}.start();

new Thread()
{
@Override
public void run() {
obj.notify();
}
}.start();

Thread.sleep(1000);
}
}




If the above program will throw java.lang.IllegalMonitorStateException

java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at WaitNotifytest$1.run(WaitNotifytest.java:21)
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at WaitNotifytest$2.run(WaitNotifytest.java:59)




notify and wait with Object monitor lock



notify() method awakes only one thread in the queue(no gaurantee in order), rest has to wait for awakened thread to notify().





public class WaitNotifytest {
static Object obj = new Object();

public static void main(String[] args) throws Exception {

new Thread() {
@Override
public void run() {
try {
synchronized (obj) {
obj.wait();
System.out.println("T1");
obj.notify();
}

} catch (Exception e) {
e.printStackTrace();
}
}
}.start();

new Thread() {
@Override
public void run() {
try {
synchronized (obj) {
obj.wait();
System.out.println("T2");
obj.notify();
}

} catch (Exception e) {
e.printStackTrace();
}
}
}.start();

new Thread() {
@Override
public void run() {
synchronized (obj) {
obj.notify();
}

}
}.start();
}
}



notifyAll


Each thread notifies after usage of object. If T1 and T2, wants to make read access of object then T3 alone notfiy to all the threads. To do this notifyAll() method get used. This method should only be called by a thread that is the owner of this object's monitor, otherwise we will get the IllegalMonitorStateException. Awakened Threads will compete each other runs/access this object.




public class WaitNotifytest {
static Object obj = new Object();

public static void main(String[] args) throws Exception {

new Thread() {
@Override
public void run() {
try {
synchronized (obj) {
obj.wait();
System.out.println("T1");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();

new Thread() {
@Override
public void run() {
try {
synchronized (obj) {
obj.wait();
System.out.println("T2");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();

new Thread() {
@Override
public void run() {
synchronized (obj) {
obj.notifyAll();
}
}
}.start();
}
}


In this program only one notifyAll method called on object to release all the lock.

Note:

  • If wait() called on the object and no notify signal received then this wait called thread will wait for ever. However, there could be a chance of thread awaking without any of notificatin like notify, timeout or interrupt. This is called spurious wakeup. This will happen in rare condition.


  • We can even specify the time, how long maximum this thread to wait to acquire the lock, even if other thread is not signalled notify/notifyAll, however object lock is released and no other thread acquires lock of this object.



wait with max timeout




public class WaitNotifytest {
static Object obj = new Object();

public static void main(String[] args) throws Exception {

new Thread() {
@Override
public void run() {
try {
synchronized (obj) {
obj.wait(400);
System.out.println("T1");
// obj.notify();

}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();

new Thread() {
@Override
public void run() {
synchronized (obj) {
try{Thread.sleep(10000);}catch(Exception e){}
// obj.notifyAll();

}
}
}.start();
}
}

2 comments:

Javin @ Basic Tutorials on FIX Protocol said...

In my opinion wait/notify is best way for inter thread communication but keep in mind if you have more than two threads its always better to use notifyAll(), Its also good to know How to find if a thread holds lock on a particular object in Java .

On a related note incorrect written multi threaded programs often results in deadlock specially if number of shared resources are more and number of accessing threads are also high its worth knowing How to find and fix deadlock in Java ?

Thanks
Javin

Java said...

also usually we invoke wait method in conjuction with notify/notifyAll, where sleep is invoked with argument as a time interval which specifies the time after which the thread will start executing automatically. So there is no concept of notify/notifyAll in case of sleep method in java.

I don't know why its confusing that wait and sleep methods have to be invoked from a synchronized block of code. You explained it well. Another useful article which I came across while searching was wait and sleep difference

Post a Comment

Recent Posts

Unix Commands | List all My Posts

Texts

This blog intended to share the knowledge and contribute to JAVA Community such a way that by providing samples and pointing right documents/webpages. We try to give our knowledege level best and no guarantee can be claimed on truth. Copyright and Terms of Policy refer blogspot.com