如何解决Java中的“双重检查锁定已损坏”声明?

如何解决Java中的“双重检查锁定已损坏”声明?,第1张

如何解决Java中的“双重检查锁定已损坏”声明?

以下是第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:明智地使用延迟初始化



欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5146820.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-18
下一篇 2022-11-17

发表评论

登录后才能评论

评论列表(0条)

保存