Q:

Happens Before relation in Java clarification on a specific example

Referring to the following link 
http://docs.oracle.com/javase/tutorial/essential/concurrency/QandE/answers.html
The example below shows that Key Statement 1 is not guaranteed to execute before key statement 2
public class BadThreads {

    static String message;

    private static class CorrectorThread
        extends Thread {

        public void run() {
            try {
                sleep(1000); 
            } catch (InterruptedException e) {}
            // Key statement 1:
            message = "Mares do eat oats."; 
        }
    }

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

        (new CorrectorThread()).start();
        message = "Mares do not eat oats.";
        Thread.sleep(2000);
        // Key statement 2:
        System.out.println(message);
    }
}

The solution states 
There are two ways you can guarantee that all changes to message will be visible to the main thread:

In the main thread, retain a reference to the CorrectorThread instance. Then invoke join on that instance before referring to message
Encapsulate message in an object with synchronized methods. Never reference message except through those methods.

Both of these techniques establish the necessary happens-before relationship, making changes to message visible.
I understand how the first solution using join can make key statement 1 "happen-before" key statement 2. 
But for the second solution, I cannot understand how using synchronized methods (say getMessage() and setMessage()) establishes this relation. 
What is the guarantee that the modified key statement 2 (System.out.println(getMessage()) will be executed after the modified key statement 1 (setMessage("Mares do eat oats")).
Key statement 2 may get a lock on message before key statement 1 or vice-versa depending on how threads are scheduled.
Also, is there a way to modify the code to make message="Mares do not eat oats" execute before message="Mares do eat oats"? 
One way I can think of is to keep a shared state variable and set it after message="Mares do not eat oats" is executed while message="Mares do eat oats" should be in a block guarded like while(!stateVariable){wait();} and then update the message. Is that right?
Thanks.

A:

Don't confuse the happens-before with any specific ordering of actions. The point of that relationship is that such an ordering exists at all, not that it is any specific ordering. In your example there is no ordering: one thread may never observe the actions of the other thread, even if you use more sleep statements and try to read what the other thread wrote.
If you want to coordinate your two actions, don't resort to wait/notify as those are very low-level and fragile mechanisms. Use something from java.util.concurrent, for example a CountDownLatch.

A:

The happens-before thing doesn't guarantee that some statement is executed before some other statement. It guarantees that if a first statement is executed before a second one, (and there is a good chance of that happening in your exemple, since both threads start at the same time, and one sleeps 1 second whereas the other one sleeps 2 seconds) the second one will see what the first one has written. 
The synchronized access to a variable guarantees that a write to this variable is visible to a subsequent read of this variable from another thread. Why? Because that's what the specification of the Java Memory Model says, and because the implementation respects the specification.
There are other ways to guarantee that: make the variable volatile, make it an AtomicReference, or store it and retrieve it from a concurrent collection.

