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();
}
}
1 comment:
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
Post a Comment