why using volatile with synchronized block?

JavaMultithreadingVolatileSynchronizedDouble Checked-Locking

Java Problem Overview


I saw some examples in java where they do synchronization on a block of code to change some variable while that variable was declared volatile originally .. I saw that in an example of singleton class where they declared the unique instance as volatile and they sychronized the block that initializes that instance ... My question is why we declare it volatile while we synch on it, why we need to do both?? isn't one of them is sufficient for the other ??

public class SomeClass {
    volatile static Object uniqueInstance = null;

    public static Object getInstance() {
        if (uniqueInstance == null) {
            synchronized (someClass.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new SomeClass();
                }
            }
        }
        return uniqueInstance;
    }
}

thanks in advance.

Java Solutions


Solution 1 - Java

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.

Solution 2 - Java

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().

Solution 3 - Java

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.)

Solution 4 - Java

You can do synchronization without using synchronized block. It's not a necessary to use volatile variable in it... volatile updates the one variable from main memory..and synchronized Update all shared variables that have been accessed from main memory.. So you can use it according to your requirement..

Solution 5 - Java

My two cents here

Frist a quick explanation of the intuition of this code

if(uniqueInstance == null) {
        synchronized(someClass.class) {
            if(uniqueInstance == null) {
                uniqueInstance = new someClass();
            }
        }
    }

The reason it checks uniqueInstance == null twice is to reduce the overhead of calling the synchronized block which is relatively slower. So called double-checked locking.

Second, the reason it uses synchronized is easy to understand, it make the two operations inside the synchronized block atomic.

Last the volatile modifier makes sure all threads see the same copy so the very first check outside of the synchronized block will see the value of uniqueInstance in a way which is "synchronized" with the synchronized block. Without the volatile modifier one thread can assign a value to uniqueInstance but the other thread may not see it by the first check. (Although the second check will see it)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDorghamView Question on Stackoverflow
Solution 1 - JavaMichał KosmulskiView Answer on Stackoverflow
Solution 2 - JavanosView Answer on Stackoverflow
Solution 3 - JavaMichael EasterView Answer on Stackoverflow
Solution 4 - Javauser1237385View Answer on Stackoverflow
Solution 5 - JavazfyView Answer on Stackoverflow