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 ?
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With