javamultithreadingconcurrencyvisibilityhappens-before

Is everything that happened before thread.start visible to the thread that is spawned calling start?


Now there are great answers to this already on stackoverflow but they don't give me the definite answer I want.

Say you have a method

Dosomething();
 doAnother();
  int x = 5;
  Runnable r = new Runnable(){
     public void run(){
     int y = x;
     x = 7;
     System.out.println(z);}
   }
   new Thread(r).start()

Now meanwhile this method is running and before calling thread.start, some global non volatile variable z was changed to 5 from 4.

Would the program be guaranteed to print 5 since z happened before thread.start?

Also if we talk about it in way, then is it safe to say that thread.start() can never be reordered ever.

Meaning in terms of that thread which is being called start on, it is as if everything up to that point is sequential. For example say we have

int k = 8;
new Thread(() -> {}).start()

Now... It wouldnt make a difference in the perspective of that thread whether the start is called first or k is assigned 8. So this can be reordered, but because of the happens before guarantee, is that not possible?

The java specs does not say a strong statement that says that. Rather it says

When a statement invokes Thread.start(), every statement that has a happens-before relationship with that statement

However k = 8 does not that a happens before relationship with that statement...

Im not even sure what they mean something has a happens before relationship with the start method unless you locked using the same monitor for example

synchronized(this){ int k = 8;}
 synchronized(this) { new Thread(() -> {}).start();}

For a scarier case what we had this code

Socket con = socket.accept();
Runnable r = new Runnable(){ 
  public void run(){
      handleRequest(con)}
 }
new Thread(r).start();

And then the new thread happens to find that con to be null?

Can someone give me a definitive answer on these topics?


Solution

  • Would the program be guaranteed to print 5 since z happened before thread.start?

    If the value of z was set by the thread which called the start() method then yes. Otherwise, no. The newly started thread is guaranteed to see the changes made by the thread that started it, NOT the ones made by other threads.

    Also if we talk about it in way, then is it safe to say that thread.start() can never be reordered ever.

    The point is - the newly started thread is guaranteed to see the value of k as 8. If the newly started thread does not read k (or any other variables that were set by the parent thread) then compilers are allowed to re-order such operations, but it doesn't matter to the programmer (the programmer gets the guarantee anyway)

    And then the new thread happens to find that con to be null?

    Assuming that the new thread has a reference to con, con is guaranteed to be initialized before the new thread starts (since the JMM guarantees that any changes made by the parent thread before the call to start() would be visible to the new thread)

    To summarize - is a thread (T1) starts another thread(T2), then any changes made by T1 before starting T2 are guaranteed to be visible to T2. As a programmer, this is what matters. Compilers are allowed to perform re-orderings as long as they do not break this guarantee. You could of-course refer to the JLS but I think you already have.