Is it advisable to always use volatile variables with synchronized blocks/methods?

As I understand it, volatile helps in memory visibility and synchronized helps in achieving execution control. Volatile just guarantees that the value read by the thread would have the latest value written to it.

Consider the following:

public class Singleton{
    private static volatile Singleton INSTANCE = null;

    private Singleton(){}

    public static Singleton getInstance(){
        if(INSTANCE==null){
             synchronized(Integer.class){
                 if(INSTANCE==null){
                     INSTANCE = new Singleton();
                 }
             }
        }
        return INSTANCE;
    }
}

In the above piece of code, we use double-checked locking. This helps us create only one instance of Singleton and this is communicated to the other threads by the creating thread as soon as possible. This is what the keyword volatile does. We need the above synchronized block because the delay in the thread reading the INSTANCE variable as null and initializing the object could cause a race condition.

Now consider the following:

public class Singleton{
    private static Singleton INSTANCE = null;

    private Singleton(){}

    public static synchronized Singleton getInstance(){
        if(INSTANCE==null){
             INSTANCE = new Singleton();
        }
        return INSTANCE;
    }
}

Say we have 2 threads t1 and t2 trying to get the Singleton object. Thread t1 enters the getInstance() method first and creates the INSTANCE object. Now this newly created object should be visible to all the other threads. If the INSTANCE variable is not volatile then how do we make sure that the object is still not in t1's memory and visible to other threads. How soon is the above INSTANCE initialized by t1 visible to other threads ?

Does this mean that it is advisable to always make variables volatile with synchronized ? In what scenarios would we not require the variable to be volatile ?

P.S I have read other questions on StackOverflow but could not find the answer to my question. Please comment before down-voting.

My question arises from the explanation given here

Jon Skeet
people
quotationmark

I think what you're missing is this from JLS 17.4.4:

An unlock action on monitor m synchronizes-with all subsequent lock actions on m (where "subsequent" is defined according to the synchronization order).

Which is very similar to the bullet about volatile variables:

A write to a volatile variable v (ยง8.3.1.4) synchronizes-with all subsequent reads of v by any thread (where "subsequent" is defined according to the synchronization order).

Then in 17.4.5:

If an action x synchronizes-with a following action y, then we also have hb(x, y).

... where hb is the "happens-before" relation.

Then:

If one action happens-before another, then the first is visible to and ordered before the second.

The memory model is incredibly complicated and I don't claim to be an expert, but my understanding is that the implication of the quoted parts is that the second pattern you've shown is safe without the variable being volatile - and indeed any variable which is only modified and read within synchronization blocks for the same monitor is safe without being volatile. The more interesting aspect (to me) is what happens to the variables within the object that the variable's value refers to. If Singleton isn't immutable, you've still potentially got problems there - but that's one step removed.

To put it more concretely, if two threads call getInstance() when INSTANCE is null, one of those threads will lock the monitor first. The write action of a non-null reference to INSTANCE happens-before the unlock operation, and that unlock operation happens-before the lock operation of the other thread. The lock operation happens-before the read of the INSTANCE variable, therefore the write happens-before the read... at which point, we are guaranteed that the write is visible to the reading thread.

people

See more on this question at Stackoverflow