why using volatile with synchronized block?
This post explains the idea behind volatile.
It is also addressed in the seminal work, Java Concurrency in Practice.
The main idea is that concurrency not only involves protection of shared state but also the visibility of that state between threads: this is where volatile comes in. (This larger contract is defined by the Java Memory Model.)
This uses the double checked locking, note that the if(uniqueInstance == null)
is not within the synchronized part.
If uniqueInstance
is not volatile, it might be "initialized" with a partially constructed object where parts of it isn't visible to other than the thread executing in the synchronized
block. volatile makes this an all or nothing operation in this case.
If you didn't have the synchronized block, you could end up with 2 threads getting to this point at the same time.
if(uniqueInstance == null) {
uniqueInstance = new someClass(); <---- here
And you construct 2 SomeClass objects, which defeats the purpose.
Strictly speaking, you don't need volatile , the method could have been
public static someClass getInstance() {
synchronized(FullDictionary.class) {
if(uniqueInstance == null) {
uniqueInstance = new someClass();
}
return uniqueInstance;
}
}
But that incurs the synchronization and serialization of every thread that performs getInstance().
Synchronization by itself would be enough in this case if the first check was within synchronized block (but it's not and one thread might not see changes performed by another if the variable were not volatile). Volatile alone would not be enough because you need to perform more than one operation atomically. But beware! What you have here is so-called double-checked locking - a common idiom, which unfortunately does not work reliably. I think this has changed since Java 1.6, but still this kind of code may be risky.
EDIT: when the variable is volatile, this code works correctly since JDK 5 (not 6 as I wrote earlier), but it will not work as expected under JDK 1.4 or earlier.