延迟初始化中的 双重检查模式 和 延迟占位类模式 你都用对了吗?

开篇:

正如《Effective Java》第二版中第71条目“慎用延迟初始化”所说:

  大多数的域应该正常的被初始化而不是延迟初始化。如果为了达到性能目标,或者为了破坏有害的初始化循环,而必须延迟初始化一个域,就可以使用相应的延迟初始化方法。

  对于实例域,就使用双重检查模式(double-check idiom);对于静态域,则使用 lazy initialization hodler class idiom。

  对于可以接受重复初始化的实例域,也可以考虑使用单检查模式(single-check idiom)。

PS:double-check idiom 也有称 double-check lock(DCL)。

实践延迟初始化:

可见,对不同的域(实例域 和 静态域)有不同的延迟初始化模式。

实例域延迟初始化代码,注意实例域是 volatile 声明的:

 1     private volatile Object field;
 2
 3     private Object getField() {
 4         Object result = field;
 5         if (result == null) {
 6             synchronized (this) {
 7                 result = field;
 8                 if (result == null) {
 9                     field = result = computeFieldValue();
10                 }
11             }
12         }
13         return result;
14     }

静态域延迟初始化代码:

1     private static class FieldHolder {
2         static final Object staticField = computeStaticFieldValue();
3     }
4
5     public static Object getStaticField() {
6         return FieldHolder.staticField;
7     }

原文地址:https://www.cnblogs.com/christmad/p/12019640.html

时间: 2024-10-24 16:34:57

延迟初始化中的 双重检查模式 和 延迟占位类模式 你都用对了吗?的相关文章

双重检查锁定与延迟初始化

在Java程序中,有时候可能需要推迟一些高开销的对象初始化操作,并且只有在使用这些对象时才进行初始化.此时程序员可能会采用延迟初始化.但要正确实现线程安全的延迟初始化需要一些技巧,否则很容易出现问题.比如,下面是非线程安全的延迟初始化对象的示例代码: public class UnsafeLazyInitialization { private static Instance instance; public static Instance getInstance() { if (instanc

JAVA 双重检查锁定和延迟初始化

双重检查锁定的由来在Java程序中,有时需要推迟一些高开销的对象的初始化操作,并且只有在真正使用到这个对象的时候,才进行初始化,此时,就需要延迟初始化技术.延迟初始化的正确实现是需要一些技巧的,否则容易出现问题,下面一一介绍. 方案1 public class UnsafeLazyInit{ private static Instance instance; public static Instance getInstance(){ if (instance == null){ instance

关于并发场景下,通过双重检查锁实现延迟初始化的优化问题隐患的记录

首先,这个问题是从<阿里巴巴Java开发手册>的1.6.12(P31)上面看到的,里面有这样一句话,并列出一种反例代码(以下为仿写,并非与书上一致): 在并发场景下,通过双重检查锁(double-checked locking)实现延迟初始化的优化问题隐患,推荐解决方案中较为简单的一种(适用于JDK5及以上的版本),即目标属性声明为volatile型. 1 public class Singleton { 2 private static Singleton instance=null; 3

单例模式中 的 双重检查锁 概念与用法

public class Singleton { //私有的 静态的 本类属性 private volatile static Singleton _instance; //私有化构造器 private Singleton() {} /* * 1st version: creates multiple instance if two thread access * this method simultaneouslyX */ public static Singleton getInstance

为什么双重检查锁模式需要 volatile ?

双重检查锁定(Double check locked)模式经常会出现在一些框架源码中,目的是为了延迟初始化变量.这个模式还可以用来创建单例.下面来看一个 Spring 中双重检查锁定的例子. 这个例子中需要将配置文件加载到 handlerMappings中,由于读取资源比较耗时,所以将动作放到真正需要 handlerMappings 的时候.我们可以看到 handlerMappings 前面使用了volatile .有没有想过为什么一定需要 volatile?虽然之前了解了双重检查锁定模式的原理

Java单例模式中双重检查锁的问题

单例创建模式是一个通用的编程习语.和多线程一起使用时,必需使用某种类型的同步.在努力创建更有效的代码时,Java 程序员们创建了双重检查锁定习语,将其和单例创建模式一起使用,从而限制同步代码量.然而,由于一些不太常见的 Java 内存模型细节的原因,并不能保证这个双重检查锁定习语有效. 它偶尔会失败,而不是总失败.此外,它失败的原因并不明显,还包含 Java 内存模型的一些隐秘细节.这些事实将导致代码失败,原因是双重检查锁定难于跟踪.在本文余下的部分里,我们将详细介绍双重检查锁定习语,从而理解它

多线程场景下延迟初始化的策略

1.什么是延迟初始化 延迟初始化(lazy initialization,即懒加载)是延迟到需要域的值时才将它初始化的行为.如果永远不需要这个值,这个域就永远不会被初始化.这种方法既静态域,也适用于实例域. 最好建议“除非绝对必要,否则就不要这么做”. 2.延迟初始化线程安全的一个策略:同步 延迟初始化的一个好处,是当域只在类的实例部分被访问,并且初始化这个域的开销很高,那就可能值得进行延迟初始化. 但是在大多数情况下,正常的初始化要优先于延迟初始化.因为在多线程的场景下,采用某种形式的同步是很

双重检查锁定原理详解

双重检查锁定与延迟初始化 在java程序中,有时候可能需要推迟一些高开销的对象初始化操作,并且只有在使用这些对象时才进行初始化.此时程序员可能会采用延迟初始化.但要正确实现线程安全的延迟初始化需要一些技巧,否则很容易出现问题.比如,下面是非线程安全的延迟初始化对象的示例代码: public class UnsafeLazyInitialization { private static Instance instance; public static Instance getInstance()

双重检查锁定

看 "java并发编程的艺术" 第3.8 双重检查锁定与延迟初始化 在Java多线程程序中,有时候需要采用延迟初始化来降低初始化类和创建对象的开销.双重检查锁定是常见的延迟初始化技术,但它是一个错误的用法.本文将分析双重检查锁定的错误根源,以及两种线程安全的延迟初始化方案. 需要注意的是, 双重检查锁定本身是错误的! 双重检查锁定的由来 在Java程序中,有时候可能需要推迟一些高开销的对象初始化操作,并且只有在使用这些对象时才进行初始化.此时,程序员可能会采用延迟初始化.但要正确实现线