Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 ?

like image 551
j2emanue Avatar asked Oct 06 '16 15:10

j2emanue


2 Answers

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.

like image 80
Andy Turner Avatar answered Oct 19 '22 21:10

Andy Turner


ThreadLocal is a facility which enables threads to have their own local copy of an object. ThreadLocals are best used with objects that can be thread safe within a thread safety policy of thread confinement (even for many objects that are not "thread safe", thread safe usage is still possible as long as no reference to them leaks out from the confining thread). ThreadLocals can not help with thread safe usage for mutable objects that are shared outside the thread that instantiates them.

The volatile keyword is used to provide a weak form of thread safety with a variable that may accessed by many different threads. A key difference is that ThreadLocals are most typically not accessed by more than one thread.

Broadly speaking, thread safety requires both visibility (the most recent updates to the variable should be visible to other threads) and mutual exclusion (state transitions must be atomic so that state can not be observed to be inconsistent). Volatile works with the Java Memory Model to guarantee that the variable will be visible, but it provides no form of mutual exclusion and therefore does not provide atomicity to state transitions in objects.

Because volatile and ThreadLocal are so different, there really is no common circumstance in which you'd be able to substitute one for the other.

like image 32
scottb Avatar answered Oct 19 '22 20:10

scottb