Reputation: 1929
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
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
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
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
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