S-C
S-C

Reputation: 1929

Can I avoid the volatile read in double checked locking once initialized like this?

By using a volatile boolean that is read only if the instance is null, can I avoid the default/frequent volatile read once the instance is initailized like so? Havent seen anyone recommend double checked locking like this, but seems to avoid volatile reads once fully initialized...

public class Singleton {

   private static volatile boolean initialized = false;
   private static Object lock = new Object();
   private static Singleton instance;

      public static Singleton getInstance(){
           if(instance != null) return instance;
           if(!initialized){
                synchronized(lock){
                   if(!initialized){
                       instance = new Singleton();
                       initialized = true;
                   }
                }
           }
           return instance;

       }

}

Upvotes: 2

Views: 424

Answers (4)

bestsss
bestsss

Reputation: 12056

volatile read is (almost) free on most hardware, volatile write is expensive, though... So why bother?

The short answer is no. between instance = new Singleton() and initialized = true on a weak memory model where stores can be reordered a reader might see an uninitialized Signleton. on x86 and sparc TSO no store-store reorder but on ARM and IA64 it does happen.

Upvotes: 0

Andrey Nudko
Andrey Nudko

Reputation: 707

If you want lazy instantiation but concerned about performance, use "inner class" approach - it is cleaner and shorter (and a tiny bit more efficient as well). Something like that:

public class Singleton {

    private static class SingletonHolder {
        private static final Singleton instance = new Singleton();
    }

    public static Singleton getInstance(){
        return SingletonHolder.instance;
    }

}

The trick is that instance is created during initialization of the inner class - that will happen when class is first referenced, which is first call to getInstance(). BTW - avoid such "static" singletons, unless there are truly good reasons to use them.

Upvotes: 0

Tomasz Nurkiewicz
Tomasz Nurkiewicz

Reputation: 340733

Your optimization attempt is not only premature, but also fruitless, quoting Are volatile variable 'reads' as fast as normal reads?:

On an x86, there is no additional overhead associated with volatile reads.

Upvotes: 1

Mat
Mat

Reputation: 206689

No, you cannot. If thread A has reached the synchronized block and is executing the

instance = new Singleton();

line, a thread B entering your function could see instance as initialized before thread A has finished constructing the object. So you risk having thread B try to work on a partially constructed object.

See the DLCP article for variations and explanations on this pattern.

Upvotes: 5

Related Questions