Guava Suppliers-class contains MemoizingSupplier:
static class MemoizingSupplier<T> implements Supplier<T>, Serializable {
final Supplier<T> delegate;
transient volatile boolean initialized;
// "value" does not need to be volatile; visibility piggy-backs
// on volatile read of "initialized".
transient T value;
MemoizingSupplier(Supplier<T> delegate) {
this.delegate = delegate;
}
@Override public T get() {
// A 2-field variant of Double Checked Locking.
if (!initialized) {
synchronized (this) {
if (!initialized) {
T t = delegate.get();
value = t;
initialized = true;
return t;
}
}
}
return value;
}
@Override public String toString() {
return "Suppliers.memoize(" + delegate + ")";
}
private static final long serialVersionUID = 0;
}
Could someone explain what does that comment mean?
"value" does not need to be volatile; visibility piggy-backs on volatile read of "initialized".
How can volatile on "initialized" field affect "value" field? According to this article we can get inconsistent combination of "initialized" and "value" fields (eg. true+null). Am I wrong?
The sentence basically means that the reads & writes of value
are ordered in a certain way with the volatile reads & writes that guarantees that the written value will be visible to the read.
If the value is not initialized, the program will execute those two statements:
value = t; //normal write
initialized = true; //volatile write
and if the value is initialized, the program will execute those two statements:
if(!initialized) { ... } //volatile read
return value; //normal read
Thanks to volatile semantics, you have a happens-before relationship between the volatile write and the volatile read and the normal read in return value
is guaranteed to see the write at value = t
. This works because the normal write is before the volatile write and the normal read is after the volatile read.
For example if the program was written like this:
initialized = true;
value = t;
return value
could return a null value because the write here does not happen before the volatile write which acts as a memory barrier and therefore it does not benefit from the volatile semantics any more.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With