Skip to content

Instantly share code, notes, and snippets.

@zencd
Last active April 5, 2023 15:12
Show Gist options
  • Save zencd/eb1418cc0c42203fc2a151f81d914cd7 to your computer and use it in GitHub Desktop.
Save zencd/eb1418cc0c42203fc2a151f81d914cd7 to your computer and use it in GitHub Desktop.
Double Checked Locking
/** private final DCLValue<Foo> foo = new DCLValue.create();
* Foo result = foo.getOrCreate(syncOn, () -> new Foo());
* Foo result = foo.get(); */
interface DCLValue<T> {
T getOrCreate(Object syncOn, Supplier<T> creator);
T get();
void set(T value);
static <T> DCLValue<T> create() {
return new DCLValueRegular<>();
}
}
class DCLValueRegular<T> implements DCLValue<T> {
private volatile T value;
@Override
public T getOrCreate(Object syncOn, Supplier<T> creator) {
T local = this.value;
if (local == null) {
synchronized (syncOn) {
local = this.value;
if (local == null) {
local = creator.get();
this.value = local;
}
}
}
return local;
}
@Override
public T get() {
return this.value;
}
@Override
public void set(T value) {
this.value = value;
}
}
/** Implemented using VarHandle */
class DCLValueVarHandle<T> implements DCLValue<T> {
private final VarHandle varHandle;
private volatile T valueField;
public DCLValueVarHandle() {
try {
MethodHandles.Lookup lookup = MethodHandles.lookup();
varHandle = lookup.findVarHandle(DCLValueVarHandle.class, "valueField", Object.class);
} catch (ReflectiveOperationException e) {
throw new IllegalStateException(e);
}
}
@Override
public T getOrCreate(Object syncOn, Supplier<T> creator) {
var obj = getAcquire();
if (obj == null) {
synchronized (syncOn) {
obj = getAcquire();
if (obj == null) {
obj = creator.get();
setRelease(obj);
}
}
}
return obj;
}
private T getAcquire() {
return (T) varHandle.getAcquire(this);
}
private void setRelease(T value) {
varHandle.setRelease(this, value);
}
@Override
public T get() {
return getAcquire();
}
@Override
public void set(T value) {
setRelease(value);
}
}
// import java.lang.invoke.MethodHandles;
// import java.lang.invoke.VarHandle;
// import java.util.function.Supplier;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment