why using volatile with synchronized block?

20,129

Solution 1

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

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

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

Share:
20,129
Dorgham
Author by

Dorgham

Updated on September 05, 2020

Comments

  • Dorgham
    Dorgham over 3 years

    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.