Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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".

like image 624
aditya soni Avatar asked Jan 22 '26 05:01

aditya soni


2 Answers

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();
    }
}
like image 62
andih Avatar answered Jan 25 '26 00:01

andih


you are locking in two different objects. in your example, "this" refers to each of the runnable instances. Besides that, variable "i" must be volatile (otherwise, different threads won't see the latest changes)

see below:

public class NotifyAndWaitExample {

    private volatile int i = 0;
    private Object lock1 = new Object();

    public static void main(String[] args) {
        NotifyAndWaitExample notifyAndWaitExample = new NotifyAndWaitExample();
        notifyAndWaitExample.execute();
    }

    private void execute() {


        Thread t1 = new Thread(new Runnable() {

            @Override
            public void run() {
                synchronized (lock1) {
                    if (i <= 0) {
                        System.out.println("i= " + i + " in t1");
                        System.out.println(Thread.currentThread().getName() + " is running");

                        try {
                            lock1.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 (lock1) {
                    i++;
                    System.out.println("i= " + i + " in t4");
                    System.out.println(Thread.currentThread().getName() + " is notifying");
                    try {
                        Thread.sleep(1000);
                        lock1.notify();
                        System.out.println("notified");
                    } catch (InterruptedException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                }
            }
        });


        t1.start();
        t4.start();
    }

}
like image 22
Jose Zevallos Avatar answered Jan 25 '26 01:01

Jose Zevallos