46
private volatile static Singleton uniqueInstance

In a singleton when using double lock method for synchronization why is the single instance declared as volatile ? Can I achieve the same functionality without declaring it as volatile ?

Josiah Yoder
  • 3,321
  • 4
  • 40
  • 58
Phoenix
  • 8,695
  • 16
  • 55
  • 88
  • Related posts [here](https://stackoverflow.com/q/18093735/465053) and [here](https://stackoverflow.com/q/12316406/465053) about why double checking is even required in first place. – RBT Feb 14 '18 at 22:33

5 Answers5

74

The volatile prevents memory writes from being re-ordered, making it impossible for other threads to read uninitialized fields of your singleton through the singleton's pointer.

Consider this situation: thread A discovers that uniqueInstance == null, locks, confirms that it's still null, and calls singleton's constructor. The constructor makes a write into member XYZ inside Singleton, and returns. Thread A now writes the reference to the newly created singleton into uniqueInstance, and gets ready to release its lock.

Just as thread A gets ready to release its lock, thread B comes along, and discovers that uniqueInstance is not null. Thread B accesses uniqueInstance.XYZ thinking that it has been initialized, but because the CPU has reordered writes, the data that thread A has written into XYZ has not been made visible to thread B. Therefore, thread B sees an incorrect value inside XYZ, which is wrong.

When you mark uniqueInstance volatile, a memory barrier is inserted. All writes initiated prior to that of uniqueInstance will be completed before the uniqueInstance is modified, preventing the reordering situation described above.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 1
    To be specific, the two reordered writes are: 1) A assigns memory address to `uniqueInstance`, and 2) `XYZ` gets something meaningful. – lcn Jun 15 '15 at 02:17
  • 1
    @dasblinkenlight : you have said that "because the CPU has reordered writes....". Please explain what reordering writes mean? – tharindu_DG Jul 24 '15 at 08:26
  • **Just as thread A gets ready to release its lock** Is it really matter? – gstackoverflow Jun 18 '19 at 09:08
  • @dasblinkenlight What is the meaning of "prevents memory writes from being re-ordered"? – Neelabh Singh Feb 15 '20 at 06:32
  • 2
    @NeelabhSingh It means, literally, what it says - if your code says it wants to write to location A before location B, having `volatile` ensures that A is actually written before B. Without `volatile` in place, CPU is free to write B before A, as long as it makes no detectable difference to the logic of your code. – Sergey Kalinichenko Feb 15 '20 at 11:04
  • what if instance has two variables, XYZ is initialized but DEF not and XYZ is initialised and before DEF can start ,other thread comes and see non null and tries to access DFE,since earlier thread did not try to start DEF write,How would volatile help? – user124 Mar 27 '21 at 23:53
  • @user124 the other thread cannot see the instance until the singleton pointer is stored. – Sergey Kalinichenko Mar 28 '21 at 12:03
  • but once you create memory. instance= new instance, you got it initialised,now t1 does this and also does intance.XYZ=123, and the next statement is instance.DEF, bit before it does the DEF statment, it got preempted after it completed instance.XYZ, now CPU does not have any pending writes with it as thread did try to start instance.DEF, how what if thread 2 comes and read it? – user124 Mar 29 '21 at 13:39
  • @user124 You do not assign ` instance= new Instance()`, you assign a local `tmp = new Instance()`, then check again, and finally do `instance = tmp`. See Mark's code in the accepted answer. – Sergey Kalinichenko Mar 29 '21 at 13:51
  • ah got that. Too much complexity :(. Can we just have static variable as , private static final Foo INSTANCE = new Foo();, and then our getInstance can just return this instead of volatile and all threading and also it is thread safe,I saw some posts suggesting this way. – user124 Mar 30 '21 at 00:24
  • Won't if help, if manually call `Thread.MemoryBarrier();` before assigning variable? – Bogdan Mart Apr 08 '21 at 21:14
  • Oh, it's Java, not c#. My bad – Bogdan Mart Apr 08 '21 at 21:14
34

Without volatile the code doesn't work correctly with multiple threads.

From Wikipedia's Double-checked locking:

As of J2SE 5.0, this problem has been fixed. The volatile keyword now ensures that multiple threads handle the singleton instance correctly. This new idiom is described in The "Double-Checked Locking is Broken" Declaration:

// Works with acquire/release semantics for volatile
// Broken under Java 1.4 and earlier semantics for volatile
class Foo {
    private volatile Helper helper = null;
    public Helper getHelper() {
        Helper result = helper;
        if (result == null) {
            synchronized(this) {
                result = helper;
                if (result == null) {
                    helper = result = new Helper();
                }
            }
        }
        return result;
    }

    // other functions and members...
}

In general you should avoid double-check locking if possible, as it is difficult to get right and if you get it wrong it can be difficult to find the error. Try this simpler approach instead:

If the helper object is static (one per class loader), an alternative is the initialization on demand holder idiom

// Correct lazy initialization in Java 
@ThreadSafe
class Foo {
    private static class HelperHolder {
       public static Helper helper = new Helper();
    }

    public static Helper getHelper() {
        return HelperHolder.helper;
    }
}
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • 3
    double checked locking can be necessary in certain situations where you have a singleton that can change during runtime, but may exist only once in your program. i.e. a login session, which you want to use to access a site, but you have to reconnect and get a new one once in a while. If the value doesn't change during runtime however, you should avoid it – Xtroce Mar 30 '16 at 09:53
  • 1
    How will you pass arguments to the constructor in case of holder idiom? – Aamir Rizwan Feb 02 '18 at 14:08
  • Doesn't the `synchronized` block ensure that the non-cached values of the fields will be retrieved, meaning that the `volatile` part is not needed anymore ? Is this still required even today? – android developer Jan 27 '21 at 14:16
11

To avoid using double locking, or volatile I use the follow

enum Singleton {
     INSTANCE;
}

Creating the instance is simple, lazy loaded and thread safe.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
2

Write to a volatile field will happen before any read operation. Below is an example code for better understanding:

private static volatile ResourceService resourceInstance;
//lazy Initialiaztion
public static ResourceService getInstance () {
    if (resourceInstance == null) { // first check
        synchronized(ResourceService.class) {
            if (resourceInstance == null) { // double check
                // creating instance of ResourceService for only one time
                resourceInstance = new ResourceService ();                    
            }
        }
    }
    return resourceInstance;
}

This link can serve you better http://javarevisited.blogspot.com/2011/06/volatile-keyword-java-example-tutorial.html

Asif Patel
  • 1,744
  • 1
  • 20
  • 27
Rajeev
  • 442
  • 1
  • 5
  • 18
-4

You can use the follow code:

private static Singleton uniqueInstance;

public static synchronized Singleton getInstance(){
    if(uniqueInstance == null){
        uniqueInstance = new Singleton();
    }
    return uniqueInstance
}
HDJEMAI
  • 9,436
  • 46
  • 67
  • 93