以下是第71项中建议的惯用语:明智地使用 Effective Java:
如果你需要使用延迟初始化来提高实例字段的性能,请使用double-check idiom。这种习惯用法避免了在初始化字段后访问字段时发生锁定的费用(项67)。习惯用法的想法是检查字段的值两次(因此,将其命名为double-check):一次不锁定,然后,如果该字段似乎未初始化,则第二次锁定。仅当第二次检查表明该字段未初始化时,该调用才会初始化该字段。因为如果字段已经初始化就没有锁定,所以声明该字段至关重要volatile(项目66)。这是成语:
// Double-check idiom for lazy initialization of instance fieldsprivate volatile FieldType field;private FieldType getField() { FieldType result = field; if (result != null) // First check (no locking) return result; synchronized(this) { if (field == null) // Second check (with locking) field = computeFieldValue(); return field; }}
此代码可能看起来有些混乱。特别是,对于局部变量结果的需求可能不清楚。此变量的作用是确保在已初始化字段的常见情况下,该字段仅被读取一次。尽管不是绝对必要的,但是这可以提高性能,并且通过应用于低级并发编程的标准可以更加优雅。在我的机器上,上述方法比不带局部变量的明显方法快25%。
在1.5版之前,由于volatile修饰符的语义不足以支持它,所以双重检查惯用语不能可靠地工作[Pugh01]。版本1.5中引入的内存模型解决了此问题[JLS,17,Goetz06 16]。今天,仔细检查惯用语是延迟初始化实例字段的一种选择技术。虽然你也可以将双重检查惯用法应用于静态字段,但没有理由这样做:惰性初始化持有人类惯用法是更好的选择。
参考
- 有效的Java,第二版
- 项目71:明智地使用延迟初始化
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)