1

Anybody can explain why this program is giving output 9? I guessed "unpredictable behavior" as its answer since main thread and thread-0 can execute in any sequence. What will join() do on main thread itself?

public class Starter extends Thread{
    private int x = 2;
    public static void main(String[] args) throws Exception{
        new Starter().makeItSo();
    }

    public Starter(){
        //Thread main
        x=5;
        start();
    }

    public void makeItSo() throws Exception{
        //Thread main
        join();
        x = x-1;
        System.out.println(x);
    }

    public void run(){ 
        //Thread-0
        x*= 2;
        }
}

Main thread starts the thread-0 and calls the run method. but if you put SOP in makeItSo(), it says that main thread is waiting there after call to join()! why? What I thought there will be no sequence between makeItSo() or run() so value of X will be unpredictable.

sHAILU
  • 165
  • 1
  • 10
  • You're right -- threads are unpredictable. Any assumption about ordering that isn't positively assured via some sort of synchronization mechanism is sure to be invalid in some scenario sometime. (Though in this case there's no real ordering to consider -- it's simple sequential logic.) – Hot Licks Jan 14 '13 at 16:34
  • 2
    You should really really make an effort to do some study on threading before doing silly things like this. – Tony The Lion Jan 14 '13 at 16:35
  • @HotLicks you're wrong in this case, the `join` is "some sort of synchronization mechanism", making the result predictable, and no, its not "simple sequential logic" – Montolide Jan 14 '13 at 16:38
  • @Montolide - So what did I say that's wrong? – Hot Licks Jan 14 '13 at 17:17
  • @HotLicks Sorry if I got it wrong, but I thought that you said that IN THAT CASE, the thread behavior is unpredictable and that is not true. – Montolide Jan 15 '13 at 16:58

4 Answers4

6

The order of execution here is fixed, because of the call to join():

  1. The constructor sets x = 5.
  2. The constructor calls start which in turn calls run in a new thread.
  3. run executes x *= 5, making x equal to 10.
  4. makeItSo is called. It calls join, thus waiting for run to end.
  5. Finally, makeItSo sets x = x-1, making x equal to 9.
rmhartog
  • 2,293
  • 12
  • 19
1

For really deep understanding this you should read 17.4.4 Synchronization Order from java language specification, that says:

Synchronization actions induce the _synchronized-with_ relation on actions, 
defined as follows:   
         ...
 - An action that starts a thread _synchronizes-with_ the first action in the 
thread it starts.
         ...
 - The final action in a thread *T1* _synchronizes-with_ any action in another
thread *T2*  that detects that *T1* has terminated. *T2* may accomplish this 
by calling *T1.isAlive()* or *T1.join()*.
CAMOBAP
  • 5,523
  • 8
  • 58
  • 93
0

You first create Starter object. In constructor you have x = 5. Than you call start(), which internally calls run(). After run your x is 10 (x *= 2). Your join() waiting run() to finishes, and after that you decrement x by 1 and that's it. x is 9. There is really nothing unpredictable here.

partlov
  • 13,789
  • 6
  • 63
  • 82
0

I believe that the confusion is caused by the way join() is called - because it's invoked from an instance method, it's like saying this.join(), where 'this' references the Starter object that was created in the main method.

This means that the main thread waits for the Starter thread to terminate and after that it decreases the value of x. This is way the result is very predictable.

Anne
  • 1