I am recently asked about java related question in an interview with following code, since I am very new to java and barely code in Java so I really have no idea what the following code does.
The question was
Select the option that describes the worst thing with the following code:
public class Bolton {
private static Bolton INST = null;
public static Bolton getInstance()
{
if ( INST == null )
{
INST = new Bolton();
}
return INST;
}
private Bolton() {
}
}
Here are the options for this question
More than one instance of Bolton can be created
A Bolton will never be created
The constructor is private and can't be called
Value can be garbage collected, and the call to getInstance may return garbage data
Which of the above options is correct? And Why?
This is a Singleton Pattern
The idea of a Singleton Pattern is to only have one available instance of a class. Therefore the constructor is set to private and the class maintains, in this case, a getInstance() method that either calls an existing instance variable, INST in this class, or creates a new one for the executing program. The answer is probably 1, because it's not thread safe. It may be confused for 3, which I had put down earlier, but that is by design, technically, so not actually a flaw.
Here's an example of Lazy Initialization, thread-safe singleton pattern from Wikipedia:
public class SingletonDemo {
private static volatile SingletonDemo instance = null;
private SingletonDemo() { }
public static SingletonDemo getInstance() {
if (instance == null) {
synchronized (SingletonDemo.class){
if (instance == null) {
instance = new SingletonDemo();
}
}
}
return instance;
}
}
Setting the instance variable to volatile tells Java to read it from memory and to not set it in cache.
Synchronized statements or methods help with concurrency.
Read more about double checked locking which is what happens for a "lazy initialization" singleton
More than one instance of Bolton can be created
This option is correct due to lack of synchronization in the above code.
Suppose two threads concurrently check for null and both will find that the value is null and both will call the constructor (which refutes singleton).
Also there is other catch in this, even if two threads dont check for null together but suppose one thread calls the constructor; but the constructor wont return till the object is constructed (assuming that the object is costly to create and requires time), so till the constructor returns some other thread might check for the null condition and still find the object as null as the object is not yet constructed.
This scenario in which some pre condition is called check-then-act which is culprit for Race.
For singleton there are two standards that are being used:
Double Checked locking
Enum based singleton pattern
UPDATE:
Here is another great article which discusses the double checked locking
Interviewer basically wants to check your knoweldge of Singleton pattern . Can the pattern be broken?. Ans is Yes. Check this or google - when singleton is not a singleton.
Best course is to use Enum based Singleton as suggested by Joshua Bloch
The getInstance() method should be synchronized, otherwise many instances could be created if multiple threads calls getInstance() at the same time. So I would select option 1.
We use Singleton Pattern when we want to have only one object of this class and it will be used every where. So to restrict the class to create many objects, we should use private for constructor of this class. And create one public function to return the object of this class.
public class MethodWin {
private int isLoggedOn=0;
private static MethodWin objectMethodWin = new MethodWin();
private MethodWin() { }
public static MethodWin getInstance() {
return objectMethodWin;
}
public void setIsLoggedOn(int value) {
this.isLoggedOn=value;
}
public int getIsLoggedOn() {
return this.isLoggedOn;
}
}
So when we need to create this obect, we should:
MethodWin meth = MethodWin.getInstance();
Original Answer is that only one instance of Bolton is created.
Through reflection we can create many objects even if the constructor is private. In multi-threaded environment there are chances to create more than one instance. Through serialization there are chances to create more than one object.
simple answer is 2) A Bolton will never be created because when you create instance the constructor will call inside constructor initialization when call getInstance method then answer will be single instance will be created.
Related
I have a class whose instances are initialized and used by underlying flatform.
class MyAttributeConverter implements AttributeConverter<XX, YY> {
public YY convertToDatabaseColumn(XX attribute) { return null; }
public XX convertToEntityAttribute(YY dbData) { return null; }
}
Nothing's wrong and I thought I need to add some static methods for being used as method references.
private static MyAttributeConverter instance;
// just a lazy-initialization;
// no synchronization is required;
// multiple instantiation is not a problem;
private static MyAttributeConverter instance() {
if (instance == null) {
instance = new MyAttributeConverter();
}
return instance;
}
// do as MyAttributeConverter::toDatabaseColumn(xx)
public static YY toDatabaseColumn(XX attribute) {
return instance().convertToDatabaseColumn(attribute);
}
public static XX toEntityAttribute(YY dbData) {
return instance().convertToEntityAttribute(attribute);
}
Still nothing seems wrong (I believe) and I don't like the instance persisted with the class and that's why I'm trying to do this.
private static WeakReference<MyAttributeConverter> reference;
public static <R> R applyInstance(Function<? super MyAttributeConverter, ? extends R> function) {
MyAttributeConverter referent;
if (reference == null) {
referent = new MyAttributeConverter();
refernce = new WeakReference<>(referent);
return applyInstance(function);
}
referent = reference.get();
if (referent == null) {
referent = new MyAttributeConverter();
refernce = new WeakReference<>(referent);
return applyInstance(function);
}
return function.apply(referent); // ##?
}
I basically don't even know how to test this code. And I'm sorry for my questions which each might be somewhat vague.
Is this a (right/wrong) approach?
Is there any chance that reference.get() inside the function.apply idiom may be null?
Is there any chance that there may be some problems such as memory-leak?
Should I rely on SoftReference rather than WeakReference?
Thank you.
Note that a method like
// multiple instantiation is not a problem;
private static MyAttributeConverter instance() {
if (instance == null) {
instance = new MyAttributeConverter();
}
return instance;
}
is not thread safe, as it bears two reads of the instance field; each of them may perceive updates made by other threads or not. This implies that the first read in instance == null may perceive a newer value written by another thread whereas the second in return instance; could evaluate to the previous value, i.e. null. So this method could return null when more than one thread is executing it concurrently. This is a rare corner case, still, this method is not safe. You’d need a local variable to ensure that the test and the return statement use the same value.
// multiple instantiation is not a problem;
private static MyAttributeConverter instance() {
MyAttributeConverter current = instance;
if (current == null) {
instance = current = new MyAttributeConverter();
}
return current;
}
This still is only safe when MyAttributeConverter is immutable using only final fields. Otherwise, a thread may return an instance created by another thread in an incompletely constructed state.
You can use the simple way to make it safe without those constraints:
private static final MyAttributeConverter instance = new MyAttributeConverter();
private static MyAttributeConverter instance() {
return instance;
}
This still is lazy as class initialization only happens on one of the specified triggers, i.e. the first invocation of the method instance().
Your usage of WeakReference is subject to the same problems. Further, it’s not clear why you resort to a recursive invocation of your method at two points where you already have the required argument in a local variable.
A correct implementation can be far simpler:
private static WeakReference<MyAttributeConverter> reference;
public static <R> R applyInstance(
Function<? super MyAttributeConverter, ? extends R> function) {
WeakReference<MyAttributeConverter> r = reference;
MyAttributeConverter referent = r != null? r.get(): null;
if (referent == null) {
referent = new MyAttributeConverter();
reference = new WeakReference<>(referent);
}
return function.apply(referent);
}
But before you are going to use it, you should reconsider whether the complicated code is worth the effort. The fact that you are accepting the need to reconstruct the object when it has been garbage collected, even potentially constructing multiple instances on concurrent invocations, suggest that you know that the construction will be cheap. When the construction is cheap, you probably don’t need to cache an instance of it at all.
Just consider
public static <R> R applyInstance(
Function<? super MyAttributeConverter, ? extends R> function) {
return function.apply(new MyAttributeConverter());
}
It’s at least worth trying, measuring the application’s performance and comparing it with the other approaches.
On the other hand, it doesn’t look like the instance was occupying a significant amount of memory nor holding non-memory resources. As otherwise, you were more worried about the possibility of multiple instances flying around. So the other variant worth trying and comparing, is the one shown above using a static final field with lazy class initialization and no opportunity to garbage collect that small object.
One last clarification. You asked
Is there any chance that reference.get() inside the function.apply idiom may be null?
Since there is no reference.get() invocation inside the evaluation of function.apply, there is no chance that such an invocation may evaluate to null at this point. The function receives a strong reference and since the calling code ensured that this strong reference is not null, it will never become null during the invocation of the apply method.
Generally, the garbage collector will never alter the application state in a way that code using strong references will notice a difference (letting the availability of more memory aside).
But since you asked specifically about reference.get(), a garbage collector may collect an object after its last use, regardless of method executions or local scopes. So the referent could get collected during the execution of the apply method when this method does not use the object anymore. Runtime optimizations may allow this to happen earlier than you might guess by looking at the source code, because what may look like an object use (e.g. a field read) may not use the object at runtime (e.g. because that value is already held in a CPU register, eliminating the need to access the object’s memory). As said, all without altering the method’s behavior.
So a hypothetical reference.get() during the execution of the apply method could in principle evaluate to null, but there is no reason for concern, as said, the behavior of the apply method does not change. The JVM will retain the object’s memory as long as needed for ensuring this correct method execution.
But that explanation was just for completeness. As said, you should not use weak nor soft references for objects not holding expensive resources.
public class Factory {
private Singleton instance;
public Singleton getInstance() {
Singleton res = instance;
if (res == null) {
synchronized (this) {
res = instance;
if (res == null) {
res = new Singleton();
instance = res;
}
}
}
return res;
}
}
It is almost correct implementation of thread-safe Singleton. The only problem I see is:
The thread #1 that is initializing the instance field can published before it will be initialized completely. Now, the second thread can read instance in a inconsistent state.
But, for my eye it is only problem here. Is it only problem here?
(And we can make instance volatile).
You example is explained by Shipilev in Safe Publication and Safe Initialization in Java. I highly recommend to read the whole article, but to sum it up look at UnsafeLocalDCLFactory section there:
public class UnsafeLocalDCLFactory implements Factory {
private Singleton instance; // deliberately non-volatile
#Override
public Singleton getInstance() {
Singleton res = instance;
if (res == null) {
synchronized (this) {
res = instance;
if (res == null) {
res = new Singleton();
instance = res;
}
}
}
return res;
}
}
Above has following problems:
The introduction of local variable here is a correctness fix, but only partial: there still no happens-before between publishing the Singleton instance, and reading of any of its fields. We are only protecting ourselves from returning "null" instead of Singleton instance. The same trick can also be regarded as a performance optimization for SafeDCLFactory, i.e. doing only a single volatile read, yielding:
Shipilev suggests to fix as follows, by marking instance volatile:
public class SafeLocalDCLFactory implements Factory {
private volatile Singleton instance;
#Override
public Singleton getInstance() {
Singleton res = instance;
if (res == null) {
synchronized (this) {
res = instance;
if (res == null) {
res = new Singleton();
instance = res;
}
}
}
return res;
}
}
There are no other problems with this example.
Normally I would never use a double checked locking mechanism anymore. To create a thread safe singleton you should let the compiler do this:
public class Factory {
private static Singleton instance = new Singleton();
public static Singleton getInstance() {
return res;
}
}
Now you are talking to make the instance volatile. I don't think this is necessary with this solution as the jit compiler now handlers the synchronization of the threads when the object is constructed. But if you want to make it volatile, you can.
Finally I would make the getInstance() and the instance static. Then you can reference Factory.getInstance() directly without constructing the Factory class. Also: you will get the same instance across all threads in your application. Else every new Factory() will give you a new instance.
You can also look at Wikipedia. They have a clean solution if you need a lazy solution:
https://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java
// Correct lazy initialization in Java
class Foo {
private static class HelperHolder {
public static final Helper helper = new Helper();
}
public static Helper getHelper() {
return HelperHolder.helper;
}
}
EDIT I've written one more answer here that should clear all the confusion.
This is a good question, and I'll try to summarize my understanding here.
Suppose Thread1 is currently initializing Singleton instance and publishes the reference (unsafely obviously). Thread2 can see this un-safe published reference (meaning it sees a non-null reference), but that does not mean that the fields that it sees via that reference (Singleton fields that are initialized via the constructor) are initialized correctly too.
As far as I can see, this happens because there could be re-ordering of the stores of the fields happening inside the constructor. Since there is no "happens-before" rules (these are plain variables), this could be entirely possible.
But that is not the only problem here. Notice that you do two reads here:
if (res == null) { // read 1
return res // read 2
These reads have no synchronization protection, thus these are racy reads. AFAIK this means that read 1 is allowed to read a non-null reference, while read 2 is allowed to read a null reference.
This btw is the same thing that the ALL mighty Shipilev explains (even if I read this article once 1/2 year I still find something new every time).
Indeed making instance volatile would fix things. When you make it volatile, this happens:
instance = res; // volatile write, thus [LoadStore][StoreStore] barriers
All "other" actions (stores from within the constructor) can not pass this fence, there will be no re-orderings. It also means that when you read the volatile variable and see a non-null value, it means that every "write" that was done before writing the volatile itself has occurred for sure. This excellent post has the exact meaning of it
This also solves the second problem, since these operations can not be re-ordered, you are guaranteed to see the same value from read 1 and read 2.
No matter how much I read and try to understand these things are constantly complicated to me, there are very few people that I know that can write code like this and reason correctly about it too. When you can (I do!) please stick to the known and working examples of double check locking :)
I do that like this:
public class Factory {
private static Factory factor;
public static Factory getInstance() {
return factor==null ? factor = new Factory() : factor;
}
}
Just simply
After some time (yeah it took 2 years, I know), I think I have the proper answer. To take it literally, the answer to this:
But, for my eye it is only problem here. Is it only problem here?
Would be yes. The way you have it right now, callers of getInstance will never see a null. But if Singleton would have fields, there is no guarantee that those fields will be correctly initialized.
Let's take this slow, since the example is beautiful, IMHO. That code you showed does a single (racy) volatile read :
public class Factory {
private Singleton instance;
public Singleton getInstance() {
Singleton res = instance; // <-- volatile RACY read
if (res == null) {
synchronized (this) {
res = instance; // <-- volatile read under a lock, thus NOT racy
if (res == null) {
res = new Singleton();
instance = res;
}
}
}
return res;
}
}
Usually, the classical "double check locking" has two racy reads of volatile, for example:
public class SafeDCLFactory {
private volatile Singleton instance;
public Singleton get() {
if (instance == null) { // <-- RACY read 1
synchronized(this) {
if (instance == null) { // <-- non-racy read
instance = new Singleton();
}
}
}
return instance; // <-- RACY read 2
}
}
Because those two reads are racy, without volatile, this pattern is broken. You can read how we can break here, for example.
In your case, there is an optimization, that does one less reading of a volatile field. On some platforms this matters, afaik.
The other part of the question is more interesting. What if Singleton has some fields that we need to set?
static class Singleton {
//setter and getter also
private Object obj;
}
And a factory, where Singleton is volatile:
static class Factory {
private volatile Singleton instance;
public Singleton get(Object obj) {
if (instance == null) {
synchronized (this) {
if (instance == null) {
instance = new Singleton();
instance.setObj(obj);
}
}
}
return instance;
}
}
We have a volatile field, we are safe, right? Wrong. The assign of obj happens after the volatile write, as such there are no guarantees about it. In plain english: this should help you a lot.
The correct way to fix this is to do the volatile write with an already build instance (fully build):
if (instance == null) {
Singleton local = new Singleton();
local.setObj(obj);
instance = local;
}
Now, the second thread can read instance in a inconsistent state.
I'm pretty sure that really is the only issue in that code. The way I understand it, as soon as the line
instance = res;
is executed, another thread could read instance and see it as non-null, and thus skips the synchronized. This means there is no happens-before relation between those two threads, because those only exist if both threads synchronize on the same object or access the same volatile fields.
The other answers already linked to Safe Publication and Safe Initialization in Java, which offers the following ways to solve the unsafe publication:
Making the instance field volatile. All threads have to read the same volatile variable, which establishes a happens-before relation
A write to a volatile field (§8.3.1.4) happens-before every subsequent read of that field.
Wrapping the singleton into a wrapper which stores the singleton in a final field. The rules for final fields are not as formally specified as the happens-before relations, the best explanation I could find is in final Field Semantics
An object is considered to be completely initialized when its constructor finishes. A thread that can only see a reference to an object after that object has been completely initialized is guaranteed to see the correctly initialized values for that object's final fields.
(Not the emphasis and restriction to the final fields, other fields might be seen in inconsistent state at least theoretically)
Making sure the singleton itself only contains final fields. The explanation would be the same as the one above.
The problem with the code mentioned in the question is that reordering can happen and a thread can get a partially constructed object of the singleton class.
When I say reordering, I mean the following:
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
/* The above line executes the following steps:
1) memory allocation for Singleton class
2) constructor call ( it may have gone for some I/O like reading property file etc...
3) assignment ( look ahead shows it depends only on memory allocation which has already happened in 1st step.
If compiler changes the order, it might assign the memory allocated to the instance variable.
What may happen is half initialized object will be returned to a different thread )
*/
}
}
}
return instance;
}
Declaring the instance variable volatile ensures a happens-before/ordered relationship on the above mentioned 3 steps:
A write to a volatile field (§8.3.1.4) happens-before every subsequent read of that field.
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...
}
FIRST OFF: Yes, I know that the best way in general to do singletons in Java is with enums, but if for some reason you need to subclass a singleton class, you can't use enums, so...
David Geary at JavaWorld published an article a long time ago on implementing singletons in Java. He argued that the following optimization to a thread-safe singleton implementation is problematic:
public static Singleton getInstance()
{
if (singleton == null)
{
synchronized(Singleton.class)
{
if(singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
(See more at: http://www.javaworld.com/javaworld/jw-04-2003/jw-0425-designpatterns.html?page=4#sthash.G8lzWOfT.dpuf)
Geary says that this 'double-checked locking' optimization
is not guaranteed to work because the compiler is free to assign a
value to the singleton member variable before the singleton's
constructor is called. If that happens, Thread 1 can be preempted
after the singleton reference has been assigned, but before the
singleton is initialized, so Thread 2 can return a reference to an
uninitialized singleton instance.
My question: Is the following change going to fix that problem or not? I've started reading Goetz's Java concurrency book and it seems that the compiler is allowed to shuffle within-thread operations, so I am not quite confident...Still, it seems to me that singleton = temp; is an atomic operation, in which case I think it should. Please explain.
public static Singleton getInstance()
{
if (singleton == null)
{
synchronized(Singleton.class)
{
if(singleton == null) {
Singleton temp = new Singleton();
singleton = temp;
}
}
}
return singleton;
}
The second code is sequentially consistent with the first code (they are strictly equivalent in a single threaded environment) and does not introduce any additional memory synchronisation points.
So yes, a compiler is authorised to rewrite the second code and turn it into the first one which means it is unsafe too.
The fact that singleton = temp; is atomic doesn't help here. It only means that singleton is either null or holds the same reference as temp. But that does not preclude temp/singleton from pointing to a "non-constructed" object.
The Java Memory Model works in terms of happens-before (HB) relationships. In both codes there is only one hb: the exit of the synchronized block hb a subsequent entry into that block. if (singleton == null) does not share any hb relationship with singleton=… so the reordering can happen.
The bottom line is that the only way to fix it is to introduce a hb between the two statements: by moving the if inside the synchronized block or by marking singleton volatile for example.
The answer depends on optimization which can be applied for the second code by compiler (it means that second one can be transformed to first one by compiler). You can write the code using AtomicReference which will allow to avoid the problem:
private static AtomicReference<Singleton> singleton = new AtomicReference<Singleton>(null);
...
public static Singleton getInstance()
{
if (singleton.get() == null)
{
synchronized(Singleton.class)
{
if(singleton.get() == null) {
singleton.compareAndSet(null, new Singleton());
}
}
}
return singleton.get();
}
Deleted as wrong, keeping the empty answer for its discussions. Wow, live and learn!
I have a class that looks like:
public class BadCodeStyle {
private static String theAnswer = null;
public static void setAnswer(String whatsNew) {
theAnswer = whatsNew;
}
public static String getAnswer() {
return (theAnswer == null) ? "I don't know" : theAnswer;
}
}
Of course that's a simplification of the actual class. What really happens is that the static method retrieves a framework object if the variable is null. Setting the variable just serves to insert a mock value for test runs where I want to isolate the code from the framework (retrofitting code for testability is fun - like poking your own eye type of fun).
When I do BadCodeStyle.setAnswer("42") the static method behaves like a Singleton (?). I did read the classloader explanation and conclude: the variable will stay as long as the class is loaded and that would be as long as the JVM runs? Is that correct?
Static class variables live as long as the class definition is loaded. This is usually until the VM exits. However, there are other ways a class can be unloaded. See, for example, this thread and this one.
Static variables are common to all objects (shared) more precisely. it doesn't belong to any instance of class (objects). so its obvious that it cannot be garbage collected with objects.
class X
{
static string str;
}
X obj1 = new X();
X obj2 = new X();
when you define X.str compiler 'll say replace with Class reference.
But it belongs to Class object. we refer to it as Class variable too. (classloader loads the class)
so its single variable (singleton 's actually a pattern that uses single object [use private constructors and using a method to return that single object] )
As you read the memory is reclaimed only when the program is done. it doesn't get (reclaimed) garbage collected in between [Non used objects 'll be garbage collected normally] .
so its lifetime exists as long as the process exists [program is running].
checkout lifetime of variables: www.cs.berkeley.edu/~jrs/4/lec/08
Sometimes when I need lazily initialized field, I use following design pattern.
class DictionaryHolder {
private volatile Dictionary dict; // some heavy object
public Dictionary getDictionary() {
Dictionary d = this.dict;
if (d == null) {
d = loadDictionary(); // costy operation
this.dict = d;
}
return d;
}
}
It looks like Double Checking idion, but not exactly. There is no synchronization and it is possible for loadDictionary method to be called several times.
I use this pattern when the concurrency is pretty low. Also I bear in mind following assumptions when using this pattern:
loadDictionary method always returns the same data.
loadDictionary method is thread-safe.
My questions:
Is this pattern correct? In other words, is it possible for getDictionary() to return invalid data?
Is it possible to make dict field non-volatile for more efficiency?
Is there any better solution?
I personally feel that the Initialization on demand holder idiom is a good fit for this case. From the wiki:
public class Something {
private Something() {}
private static class LazyHolder {
private static final Something INSTANCE = new Something();
}
public static final Something getInstance() {
return LazyHolder.INSTANCE;
}
}
Though this might look like a pattern intended purely for singleton control, you can do many more cool things with it. For e.g. the holder class can invoke a method which in turn populates some kind of data.
Also, it seems that in your case if multiple threads queue on the loadDictionary call (which is synchronized), you might end up loading the same thing multiple times.
The simplest solution is to rely on the fact that a class is not loaded until it is needed. i.e. it is lazy loaded anyway. This way you can avoid having to do those checks yourself.
public enum Dictionary {
INSTANCE;
private Dictionary() {
// load dictionary
}
}
There shouldn't be a need to make it any more complex, certainly you won't make it more efficient.
EDIT: If Dictionary need to extend List or Map you can do.
public enum Dictionary implements List<String> { }
OR a better approach is to use a field.
public enum Dictionary {
INSTANCE;
public final List<String> list = new ArrayList<String>();
}
OR use a static initialization block
public class Dictionary extends ArrayList<String> {
public static final Dictionary INSTANCE = new Dictionary();
private Dictionary() { }
}
Your code is correct. To avoid loading more than once, synchronized{} would be nice.
You can remove volatile, if Dictionary is immutable.
private Dictionary dict; // not volatile; assume Dictionary immutable
public Dictionary getDict()
if(dict==null)
dict = load()
return dict;
If we add double checked locking, it's perfect
public Dictionary getDict()
if(dict==null)
synchronized(this)
if(dict==null)
dict = load()
return dict;
Double checked locking works great for immutable objects, without need of volatile.
Unfortunately the above 2 getDict() methods aren't theoretically bullet proof. The weak java memory model will allow some spooky actions - in theory. To be 100% correct by the book, we must add a local variable, which clutters our code:
public Dictionary getDict()
Dictionary local = dict;
if(local==null)
synchronized(this)
local = dict;
if(local==null)
local = dict = load()
return local;
1.Is this pattern correct? In other words, is it possible for getDictionary() to return invalid data?
Yes if it's okay that loadDictionary() can be called by several threads simultaneously and thus different calls to getDictionary() can return different objects. Otherwise you need a solution with syncronization.
2.Is it possible to make dict field non-volatile for more efficiency?
No, it can cause memory visibility problems.
3.Is there any better solution?
As long as you want a solution without syncronization (either explicit or implicit) - no (as far as I understand). Otherwise, there are a lot of idioms such as using enum or inner holder class (but they use implicit synchronization).
Just a quick stab at this but what about...
class DictionaryHolder {
private volatile Dictionary dict; // some heavy object
public Dictionary getDictionary() {
Dictionary d = this.dict;
if (d == null) {
synchronized (this) {
d = this.dict;
if (d == null) { // gated test for null
this.dict = d = loadDictionary(); // costy operation
}
}
return d;
}
}
Is it possible to make dict field non-volatile for more efficiency?
No. That would hurt visibility, i.e. when one thread initializes dict, other threads may not see the updated reference in time (or at all). This in turn would results in multiple heavy initializations, thus lots of useless work , not to mention returning references to multiple distinct objects.
Anyway, when dealing with concurrency, micro-optimizations for efficiency would be my last thought.
Initialize-on-demand holder class idiom
This method relies on the JVM only
intializing the class members upon
first reference to the class. In this
case, we have a inner class that is
only referenced within the
getDictionary() method. This means
DictionaryHolder will get initialized
on the first call to getDictionary().
public class DictionaryHolder {
private DictionaryHolder ()
{
}
public static Dictionary getDictionary()
{
return DictionaryLazyHolder.instance;
}
private static class DictionaryLazyHolder
{
static final DictionaryHolder instance = new DictionaryHolder();
}
}