java重置用doublecheck习惯用法加载的字段lazyloaded
考虑“对实例字段进行惰性初始化的双检查习惯用法”:
// Item 71 in Effective Java copied from this interview with Bloch. private volatile FieldType field; FieldType getField() { FieldType result = field; if (result == null) { // First check (no locking) synchronized(this) { result = field; if (result == null) // Second check (with locking) field = result = computeFieldValue(); } } return result; }
我希望能够以安全的方式重置字段(在我的情况下,强制从数据库再次加载)。我假设我们可以通过重置方法来实现这一点:
void reset() { field = null; }
这是重置字段的标准方法吗?安全吗?有陷阱吗?我这样问是因为布洛赫对双重检查的延迟加载给出了以下警告:“这个习惯用法非常快速,但也非常复杂和微妙,所以不要试图以任何方式修改它。只是复制和粘贴——通常不是一个好主意,但在这里是合适的。”
提前谢谢, 来自喜马拉雅山脉的普拉亚
# 1 楼答案
我认为reset()方法不正确。如果你阅读第71项,你会发现:
{bq 1}$延迟初始化并不认为字段可能会更改。如果这些运算符之间的字段设置为空:
FieldType result = field;
if (result == null) { // First check (no locking)
getField()提供了错误的结果
# 2 楼答案
我认为这应该是安全的,但这只是因为您将字段存储在局部变量中。完成后,即使另一个线程正在中途重置字段的值,局部变量引用也无法神奇地变为null