In the below code about the synchronisation between threads, according to the output generated why is the control being transferred to the execution of the new thread despite the lock being acquired for the same object "dt" in the main method ?

public class DemoThread extends Thread {

public DemoThread() {
}

public void run() {
    int i=0;
    synchronized(this) {
        while(++i<=5) {
            sum=i;
            try{
                sleep(1000);
                System.out.println("Woke up from sleep");
               if(i>=2) this.notify();
            }catch(InterruptedException ie) {
                ie.printStackTrace();
                System.exit(1);
            }
        }
    }
}
private static int sum;    

public static void main(String... args) {

    DemoThread dt = new DemoThread();
    dt.start();

    synchronized(dt) {
        try{
            System.out.println("main here");
            dt.wait();
            System.out.println("main here again");
            System.out.println("sum = " + sum);
        }catch(InterruptedException ie){
            ie.printStackTrace();
            System.exit(1);
        }
    }        
}
}
Output :

main here
Woke up from sleep
Woke up from sleep
Woke up from sleep
Woke up from sleep
Woke up from sleep
main here again
sum = 5 

The wait method releases the thread's lock.

Then why isnt it being notified when calls of notify() are made inside the while loop?

After a notify any ready thread(s) may be scheduled for execution. You have no control over which one.