I've been using LazyReference
class for a few years (not on a regular basis of course, but sometimes it is very useful). The class can be seen here. Credits go to Robbie Vanbrabant (class author) and Joshua Bloch with his famous "Effective Java 2nd edt." (original code).
The class works correctly (in Java 5+) but there is one little potential issue. If instanceProvider
returns null
(well it must not according to Guice Provider.get()
contract, but…) then on every execution of LazyReference.get()
method the LOCK will be held and instanceProvider.get
will be called over and over again. It looks like a good punishment for those who break the contracts (he-he), but what if one really needs to lazily initialize a field with the possibility to set the null
value?
I modified LazyReference a little bit:
public class LazyReference<T> {
private final Object LOCK = new Object();
private volatile T instance;
private volatile boolean isNull;
private final Provider<T> instanceProvider;
private LazyReference(Provider<T> instanceProvider) {
this.instanceProvider = instanceProvider;
}
public T get() {
T result = instance;
if (result == null && !isNull) {
synchronized (LOCK) {
result = instance;
if (result == null && !isNull) {
instance = result = instanceProvider.get();
isNull = (result == null);
}
}
}
return result;
}
}
IMHO it should work just fine (if you have another opinion please post your comments and criticisms). But I wonder what will happen if I remove the volatile
modifier from isNull
boolean (leaving it for instance
of course)? Will it still work correctly?