I have class designed for lazy initialization and storing objects which creation is not necessary threadsafe. Here is the code:
class SyncTest {
private static final Object NOT_INITIALIZED = new Object();
private Object object;
/**
* It's guaranteed by outer code that creation of this object is thread safe
* */
public SyncTest() {
object = NOT_INITIALIZED;
}
public Object getObject() {
if (object == NOT_INITIALIZED) {
synchronized (NOT_INITIALIZED) {
if (object == NOT_INITIALIZED) {
final Object tmpRef = createObject();
object = tmpRef;
}
}
}
return object;
}
/**
* Creates some object which initialization is not thread safe
* @return required object or NOT_INITIALIZED
* */
private Object createObject() {
//do some work here
}
}
Here final
variable tmpRef
is used for storing created object before assigning it to checked variable object
. This works in tests but I can't say it's correct for sure and won't be optimsed by compiler.
Can this appraoch be used or object
field must be declared as volatile
?
Also variant with wrapper class was considered where the line
final Object tmpRef = createObject();
must be replaced with this one:
Object tmpRef = new FinalWrapper(createObject()).getVal();
Wrapper class looks like this:
private class FinalWrapper {
private final Object val;
public FinalWrapper(Object val) {
this.val = val;
}
public Object getVal() {
return val;
}
}
Can some of this examples be safely used in multithreaded environment (especially variant with final local field)?