Search code examples
javamultithreadingwaitnotify

Notify and wait code scenario


public class NotifyAndWaitExample2 {
    static int i = 0;

    public static void main(String[] args) {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (this) {
                    if (i <= 0) {
                        System.out.println("i=" + i + "in t1");
                        System.out.println(Thread.currentThread().getName() + "is running");
                        try {
                            wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println(Thread.currentThread().getName() + "is waken up");
                }
            }
        });
        Thread t4 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (this) {
                    i++;
                    System.out.println("i=" + i + "in t4");
                    System.out.println(Thread.currentThread().getName() + "is notifying");
                    try {
                        Thread.sleep(1000);
                        notify();
                        System.out.println("notified");
                    } catch (InterruptedException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                }
            }
        });
        t1.start();
        t4.start();
    }
}

Here It is showing ouptut:-

i=0in t1 
i=1in t4 
Thread-0is running 
Thread-1is notifying 
notified 

One last line should also be printed in output i.e; "Thread-0 is waken up". Why after printing "notified" it doesn't loose lock to thread "t1 run() method " and continue with the code after wait() in t1 . i.e it should print "Thread-0 is waken up" after printing "notified".


Solution

  • Your synchronized blocks have "no" effect.

    Your synchronized(this) just gets the lock for the Runnable instance where you also implement the run method.

    Your Thread t1 will never be notified, it waits for the Runnable where you use the wait() method to get notified. The only object that holds a reference to this Runnable is the Thread Object t1 and that will (usually) not call notify() or notifyAll() on that Runnable.

    I'm using an int[] for storing the int value as well as for holding the lock / monitor. The solution is only to show you how you could do it, not meant that this is good practice to do it this way.

    I'd recommend to read a good tutorial about how synchronized in Java works.

    I've modified you example so that it works as you expect.

    public class NotifyAndWaitExample2 {
        private static int[] i = {0};
    
        public static void main(String[] args) {
            Thread t1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    synchronized (i) {
                        if (i[0] <= 0) {
                            System.out.println("i=" + i[0] + " in t1");
                            System.out.println(Thread.currentThread().getName() + " is running");
                            try {
                                i.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        System.out.println(Thread.currentThread().getName() + " is waken up");
                    }
                }
            });
            Thread t4 = new Thread(new Runnable() {
                @Override
                public void run() {
                    synchronized (i) {
                        i[0]++;
                        System.out.println("i=" + i[0] + "in t4");
                        System.out.println(Thread.currentThread().getName() + " is notifying");
                        try {
                            Thread.sleep(1000);
                            i.notifyAll();
                            System.out.println("notifying");
                        } catch (InterruptedException e1) {
                            // TODO Auto-generated catch block
                            e1.printStackTrace();
                        }
                    }
                }
            });
            t1.start();
            t4.start();
        }
    }