Why do wait and notify function not working properly on same class lock

Why do wait and notify function not working properly on same class lock?

Please see check below code for wait and notify functionality and its output.

Output:

Thread-1
Thread-2
Thread-2 after notify

Expected Result:

Thread-1
Thread-2
Thread-2 after notify
Thread-1 after wait    

Code:

public class WaitAndNotify1 {    
    public static void main(String[] args) {        
        Thread t1=new Thread(new Runnable(){            
            @Override
            public void run(){                
                System.out.println("Thread-1");                
                try {
                    synchronized (this) {
                        wait();
                        System.out.println("Thread-1 after wait");
                    }                    
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread t2=new Thread(new Runnable(){            
            @Override
            public void run(){
                try {
                    Thread.sleep(4000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Thread-2");
                synchronized (this) {
                    notify();
                    System.out.println("Thread-2 after notify");
                }
            }
        });
        t1.start();
        t2.start();
    }
}
Jon Skeet
people
quotationmark

You're using this from an anonymous inner class - so it refers to the instance of that anonymous inner class. There are two different instances (of different anonymous inner classes) so you're calling wait() on a different object from the one you're calling notify() on.

You don't actually have an instance of WaitAndNotify1 to synchronize on at the moment. You could move the code to an instance method, then use WaitAndNotify1.this to refer to the instance - at which point you'll get your expected output:

public class WaitAndNotify1 {
    public static void main(String[] args) {
        new WaitAndNotify1().test();
    }

    public void test() {
        Thread t1=new Thread(new Runnable(){            
            @Override
            public void run(){                
                System.out.println("Thread-1");                
                try {
                    synchronized (WaitAndNotify1.this) {
                        WaitAndNotify1.this.wait();
                        System.out.println("Thread-1 after wait");
                    }                    
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread t2=new Thread(new Runnable(){            
            @Override
            public void run(){
                try {
                    Thread.sleep(4000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Thread-2");
                synchronized (WaitAndNotify1.this) {
                    WaitAndNotify1.this.notify();
                    System.out.println("Thread-2 after notify");
                }
            }
        });
        t1.start();
        t2.start();
    }
}

people

See more on this question at Stackoverflow