RoyalTiger
RoyalTiger

Reputation: 541

Thread Signalling Sequence

In the below code I have implemented inter Thread communication using wait() -notify() and it is giving me expected output. expected Output : 123456789 Actual output : 123456789

My question is , is there any guarantee that always 'Main Thread' will get the first chance to execute, since Thread scheduling depends on jvm. And if 'child thread' gets the first chance, the notify() signal will miss and the 'main Thread ' will wait forever. How can I confirm that 'Main thread' will execute first always. Also please confirm if the below code can be improved.

package com.test.Thread;

public class ThreadExample1 {

    public static void main(String[] args) throws InterruptedException{

        ThreadChild1 lockingObj = new ThreadChild1();
        lockingObj .start();
        synchronized(lockingObj ){
            for(int i=1;i<10;i++){
                System.out.println("Main "+i);
            }
            lockingObj.wait();
            System.out.println("Main got notified");

        }

    }

}

class ThreadChild1 extends Thread{

    public void run(){
        synchronized(this){
            for(int i=1;i<10;i++){
                System.out.println("Child "+i);
            }
            this.notify();
            }
    }
}

Upvotes: 0

Views: 47

Answers (2)

n247s
n247s

Reputation: 1918

While this works correctly on your system, it is not a guranty as your suspicion might become true on a different system. Threading behavior is verry difficult/impossible to predict. Therefore I like to think in worst case scenarios, and if I can come up with a possible breaking situation (as you just described one) I simply redesign to make sure it will work.

A nice trick to test your code is to suspend/pause threads on critical moments by either adding a breakpoint in your IDE, adding a verry time consuming task/call if possible (not failsafe), or by fysically pausing the thread(not always ideal). Besides Im sure there is are libraries to expand on this type of tesing.

I hope this helps you a bit in the right direction.

Upvotes: 1

Erwin Bolwidt
Erwin Bolwidt

Reputation: 31279

Your code is wrong for the reason that you mentioned yourself: you can't be sure which thread goes first. There are other things that could go wrong - wait can wake up without a notify.

You can read about it in the Javadoc for the wait method, which also explains what you should do:

As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop:

synchronized (obj) {
     while (<condition does not hold>)
         obj.wait();
     ... // Perform action appropriate to condition
 }

In your code, you can solve it with a boolean variable that expresses the condition "I was notified":

public class ThreadExample1 {

    public static void main(String[] args) throws InterruptedException {
        ThreadChild1 lockingObj = new ThreadChild1();
        lockingObj.start();

        synchronized (lockingObj) {
            for(int i = 1; i < 10; i++) {
                System.out.println("Main " + i);
            }
            while (!lockingObj.haveNotified) {
                lockingObj.wait();
            }
            System.out.println("Main got notified");
        }

    }

}

class ThreadChild1 extends Thread{
    private boolean haveNotified;
    public void run(){
        synchronized (this) {
            for (int i = 1; i < 10; i++) {
                System.out.println("Child " + i);
            }
            haveNotified = true;
            this.notify();
        }
    }
}

Upvotes: 2

Related Questions