1

I have the following code:

   public class ThreadDemo {
    public static void main(String[] args) throws InterruptedException {
        ThreadImpl thr = new ThreadImpl();
        thr.start();
        Thread.sleep(1000);
        synchronized(thr){
            System.out.println( "MAIN "+thr.hashCode());
            System.out.println("Main -->got the lock");
            thr.wait();
            System.out.println("Main -->Done with waiting");
        }
    }
}

class ThreadImpl extends Thread{
    public synchronized void sayHello(){
        System.out.println("Ssay hello ");
    }
    @Override
    public void run() {
        synchronized(this){
            System.out.println( "METHOD "+this.hashCode());
            System.out.println("METHOD Got the lock ");
            System.out.println("METHOD Going for sleep ");
                for(int i =0;i< 100000;i++);
            try {
                Thread.sleep(2000);
                System.out.println("METHOD Woke up ");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("METHOD Done leaving the thread");
        }
    }
}

In the main method of ThreadDemo, I am creating a thread object ThreadImpl and starting it. Next, the main thread sleeps for 1000ms. The run method of the thread will be executed in a separate thread.As part of this it loops 100000 times and sleeps for 2000ms. Then it exits the method. The main thread wakes up and acquires the lock for "thr" and then goes on wait state. As the other thread has completed its execution, this wait should be forever. However, I see the following result:

METHOD 1729414014
METHOD Got the lock
METHOD Going for sleep
METHOD Woke up
METHOD Done leaving the thread
MAIN 1729414014
Main -->got the lock
Main -->Done with waiting

How is it that the main method continues its execution when no one has notified it?

  • 3
    https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#join-long-. Don't sublcass Thread. Don't synchronize on a Thread. Don't wait on a Thread. – JB Nizet Mar 29 '18 at 06:58
  • 2
    because you have a typo `for(int i =0;i< 100000;i++);` - remove the semi-colon – Scary Wombat Mar 29 '18 at 06:58
  • 3
    Synchronizing the run() method of a Runnable is completely pointless unless you want to share the Runnable itself – Ubercool Mar 29 '18 at 06:59
  • 3
    `synchronizing` on `Thread` has **many** strange implications; not least that a `Thread` calls `notifyAll` on itself on death - this is part of the `join` framework. Unless you really know what you are doing **don't** synchronize on a `Thread` instance. Better yet, forget the `synchronized` keyword exists altogether. – Boris the Spider Mar 29 '18 at 07:01
  • @ScaryWombat the semicolon was deliberate. I want it to spin 100000 times without doing anything. The issue here is who is waking up the main thread(9th line of the code snippet.) – user9567992 Mar 29 '18 at 13:49
  • If that is the case I feel that the thread would have finished by the time that your `Main` has finished sleeping – Scary Wombat Mar 30 '18 at 00:12

1 Answers1

0

This is spurious wake-up, see jls:

The thread may be removed from the wait set due to any one of the following actions, and will resume sometime afterward:

  • A notify action being performed on m in which t is selected for removal from the wait set.
  • A notifyAll action being performed on m.
  • An interrupt action being performed on t.
  • If this is a timed wait, an internal action removing t from m's wait set that occurs after at least millisecs milliseconds plus nanosecs nanoseconds elapse since the beginning of this wait action.
  • An internal action by the implementation. Implementations are permitted, although not encouraged, to perform "spurious wake-ups", that is, to remove threads from wait sets and thus enable resumption without explicit instructions to do so.
xingbin
  • 27,410
  • 9
  • 53
  • 103