I was reading this: https://en.m.wikipedia.org/wiki/Double-checked_locking
And in section Usage in Java, last example:
Semantics of final field in Java 5 can be employed to safely publish the helper object without using volatile:
public class FinalWrapper<T> {
public final T value;
public FinalWrapper(T value) {
this.value = value;
}
}
public class Foo {
private FinalWrapper<Helper> helperWrapper;
public Helper getHelper() {
FinalWrapper<Helper> tempWrapper = helperWrapper;
if (tempWrapper == null) {
synchronized (this) {
if (helperWrapper == null) {
helperWrapper = new FinalWrapper<Helper>(new Helper());
}
tempWrapper = helperWrapper;
}
}
return tempWrapper.value;
}
}
The local variable tempWrapper is required for correctness: simply using helperWrapper for both null checks and the return statement could fail due to read reordering allowed under the Java Memory Model.[14] Performance of this implementation is not necessarily better than the volatile implementation.
Why tempWrapper is required for correctness? Can't I just remove it and replace with helperWrapper. As far as I understand, the reference to object being created of FinalWrapper<Helper> won't escape to other threads before it's final field value has been initialized in constructor. If some other thread read helperWrapper as not null, then it must have correct value for value.
volatileinstance field. Concurrency in Practice (by Goetz) also has a section on this: Double-checked locking. There, DCL is considered to be an antipattern; and it is explicitly stated that it only works correctly if the field isvolatile.finalwrapper not being mentioned doesn't mean it isn't safe (and I think it should work given thatfinalmakes sure the object is fully initialized before it's set etc).