Consider the following scenario borrowed from Memory Consistency - happens-before relationship in Java:
package happen.before;
public class HappenBeforeRelationship {
private static int counter = 0;
private static void threadPrintMessage(String msg){
System.out.printf("[Thread %s] %s\n", Thread.currentThread().getName(), msg);
}
public static void main(String[] args) {
threadPrintMessage("Increase counter: " + ++counter);
Thread t = new Thread(new CounterRunnable());
t.start();
try {
t.join();
} catch (InterruptedException e) {
threadPrintMessage("Counter is interrupted");
}
threadPrintMessage("Finish count: " + counter);
}
private static class CounterRunnable implements Runnable {
@Override
public void run() {
threadPrintMessage("start count: " + counter);
counter++;
threadPrintMessage("stop count: " + counter);
}
}
I know there is a rule in JLS guarantees that Thread.start
happens before all actions in the started thread.
When a statement invokes Thread.start, every statement that has a happens-before relationship with that statement also has a happens-before relationship with every statement executed by the new thread. The effects of the code that led up to the creation of the new thread are visible to the new thread.
But it does not claim that statements before Thread.start
has a happens-before relationship with it.
So I wonder that could Thread.start
be reordered so that the program could not get the expected output (counter=2)? If not, which part of JLS specifies that Thread.start
could not be reordered?
Another question:
What happens if join()
is put after threadPrintMessage("Finish count: " + counter);
? Is it possible that stop count: 1
is printed?