Guava: MemoizingSupplier thread safety

Guava Suppliers-class contains MemoisingSupplier:

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; } 

Can someone explain what this comment means?

β€œmeaning” does not have to be volatile; Visibility of copies on mutable reading is "initialized".

How does a volatile initialized field affect a value field? According to this article, we can get a contradictory combination of the "initialized" and "value" fields (for example, true + null). Am I mistaken?

+6
source share
1 answer

The sentence basically means that the reading and writing of value ordered in a certain way by means of mutable readings and records, ensuring that the written value is visible for reading.


(simplified) proof

If the value is not initialized, the program will execute these two statements:

 value = t; //normal write initialized = true; //volatile write 

and if the value is initialized, the program will execute these two statements:

 if(!initialized) { ... } //volatile read return value; //normal read 

Thanks to volatile semantics, you have a connection between volatile writing and volatile reading, and normal reading in return value ensures that you see the record in value = t . This works because normal writing before choppy writing and normal reading after choppy reading.


Why order is important

For example, if the program was written as follows:

 initialized = true; value = t; 

return value can return a null value because the write here is not performed until the volatile write, which acts as a memory barrier, and therefore it no longer benefits from volatile semantics.

+5
source

Source: https://habr.com/ru/post/986721/


All Articles