4

In the statement below, the wait() method is executed even though no notify is called but the statement below wait() are executing only after laurel thread completes its execution.

I tried using other objects for locking in synchronization of hardy block this time wait method is still waiting forever, can someone explain me why statement after wait() was executed?

package delagation;

public class Solution extends Thread {

    static Thread laurel, hardy;

    public static void main(String[] args) throws InterruptedException {
        laurel = new Thread() {
            public void run() {
                System.out.println("A");
                try {
                    hardy.sleep(1000);
                } catch (Exception e) {
                    System.out.println("B");
                }
                System.out.println("C");
            }
        };
        hardy = new Thread() {
            public void run() {
                System.out.println("D");
                try {
                    synchronized(laurel) {
                        laurel.wait();
                        //wait method is called here, 
                        //There is not notify in this class, 
                        //but the statement below are executing
                        System.out.println(Thread.currentThread().getName());
                    }
                } catch (Exception e) {
                    System.out.println("E");
                }
                System.out.println("F");
            }
        };
        laurel.setName("laurel");
        hardy.setName("hardy");
        laurel.start();
        hardy.start();
    }
}
Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
sibi
  • 59
  • 3
  • 4
    What exactly do you expect this code to do?! When a `Thread` dies it calls `notifyAll`. Never `extends Thread`. Never `synchronized` on a `Thread`. Not unless you _really_ know what you are doing... – Boris the Spider May 19 '17 at 18:15
  • 5
    @BoristheSpider And never practice, punch him on his face please! – Yahya May 19 '17 at 18:17
  • I know there's a duplicate of this, but I can't find it. – shmosel May 19 '17 at 18:50
  • 1
    All the comments by Boris are spot on. He gives a lot of helpful feedback in three lines of comments. I really don't see how this translates to face punching. – GhostCat May 20 '17 at 04:22

1 Answers1

4

You don't need to postulate a spurious wakeup to explain what's going on here. When laurel terminates it sends a notifyAll to the threads that are waiting on it. (This is how Thread.join works.)

See the api doc for Thread#join:

This implementation uses a loop of this.wait calls conditioned on this.isAlive. As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.

Also, always wait in a loop, using a condition; see the Oracle concurrency tutorial, especially the Guarded Blocks page. (From the description you can see join waits in a loop where the tested condition is isAlive on the thread joined to, so it is s good example. You can find the join method in the jdk source for the Thread class.)

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
  • *You're correct that this is not a spurious wakeup.* Source? – shmosel May 19 '17 at 18:51
  • @shmosel: this is repeatable, spurious wakeups are created by race conditions and shouldn't be this predictable. But reworded just to be safe. Better? – Nathan Hughes May 19 '17 at 18:54
  • I don't know that unpredictability is relevant to Java's definition of "spurious wakeup". Here's the definition I found on the `Object` class: *A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup.* – shmosel May 19 '17 at 19:07
  • @shmosel: unpredictability seems to be typical for race conditions. Anyway i agreed the wording could be improved. Also i found a question that this is a duplicate of. – Nathan Hughes May 19 '17 at 19:10
  • 1
    You answered and you closed out the question. Even when done in good spirits, I find that questionable. When the question has a good dup close it. If not put up an answer. But don't answer yourself whilst locking out other answer afterwards. Nonetheless both your answer and the dup are OK. – GhostCat May 20 '17 at 04:25
  • @GhostCat: yeah i see how you can take it like that. Closing was something i didnt think of until i noticed shmosel's comment and started looking gor a dupe myself, then was surprised at how good a match the other was. I really didn't think there was any more to say about this question that wasn't covered in the answer here or in the dupe target, but reopening since you think this is unfair. – Nathan Hughes May 20 '17 at 14:54