Search code examples
javamultithreadingvolatilethread-local

volatile vs threadLocal in java


Lets take SimpleDateFormat as an example since it is not thread safe.

I could allow each thread to have its own copy of SimpleDateFormat using threadLocal like this:

 private static final ThreadLocal<SimpleDateFormat> formatter = new ThreadLocal<SimpleDateFormat>(){
    @Override
    protected SimpleDateFormat initialValue()
    {
        return new SimpleDateFormat("yyyyMMdd HHmm");
    }
};

But the volatile keyword guarantees that a thread will have the most recent copy of the variable. So could i not do this instead:

volatile SimpleDateFormat myformatter;

and achieve the same thread safety ?


Solution

  • the volatile keyword guarantees that a thread will have the most recent copy of the variable

    Of the volatile variable only, not its fields.

    Also, volatile is only useful if you need to change the value of the variable. In your use case, final looks like it would be more appropriate:

    private static final SimpleDateFormat format = ...
    

    This also guarantees that you will have the most recent value of the variable - because it can only be assigned its value once, and static final has guarantees the visibility once the class is fully loaded.


    But this isn't the reason why SimpleDateFormat is not thread safe anyway: it has mutable state which it uses to store intermediate values when formatting the date.

    If one thread calls format while another is also in the format method for the same SimpleDateFormatter instance, these intermediate variables get stomped unpredictably, leading to interference between the threads, and hence unpredictable output.

    It doesn't matter whether or not the values of these intermediate variables are up-to-date when read/written by another thread - their updating can be interspersed.

    In short, volatile doesn't prevent thread interference, and so is not an appropriate alternative to a ThreadLocal here.