同意关于 `synchronized` 的观点。
关于可能的并发错误的观察很到位。以下是相关代码。特别是 `deref` 使用了 `volatile`/非同步策略
```
public class Delay implements IDeref, IPending {
volatile Object value;
Object unsynchronizedValue;
ReentrantLock lock;
private static class ExceptionalValue {
private final Object v;
public ExceptionalValue (Object v) {
this.v = v;
}
}
private static class PendingValue {
private final Object v;
public PendingValue (Object v) {
this.v = v;
}
}
public Delay(IFn f){
Object v = new PendingValue(f);
unsynchronizedValue = v;
value = v;
lock = new ReentrantLock();
}
private static Object getOrThrow(Object v) {
if (v instanceof ExceptionalValue) {
return Util.sneakyThrow((Throwable)(((ExceptionalValue)v).v));
} else {
return v;
}
}
public Object deref() {
if (unsynchronizedValue instanceof PendingValue) {
// Volatile read
Object v = value;
if (v instanceof PendingValue) {
try {
lock.lock();
// Volatile read after lock held, in case it changed
Object vAfter = value;
if (vAfter instanceof PendingValue) {
IFn f = (IFn)(((PendingValue)vAfter).v);
Object vComputed = null;
try {
vComputed = f.invoke();
} catch (Throwable t) {
vComputed = new ExceptionalValue(t);
}
unsynchronizedValue = vComputed;
value = vComputed;
return getOrThrow(vComputed);
} else {
return getOrThrow(vAfter);
}
} finally {
lock.unlock();
}
} else {
return v;
}
} else {
return getOrThrow(unsynchronizedValue);
}
}
... // `force`, `isRealized` 实现
}
```