Last active
April 5, 2023 15:12
-
-
Save zencd/eb1418cc0c42203fc2a151f81d914cd7 to your computer and use it in GitHub Desktop.
Double Checked Locking
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** 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