Java DCL(Double Check Lock)单例模式详解

单例模式是应用最广的模式之一。相信大家都非常熟悉了,什么,不熟悉?你都单例模式单刷了二十年了,还不懂?好吧,不懂的同学请自行百度。

首先是最经典的痴汉...不是,饿汉模式:

public class Girlfiriend extends Friend{
  private static final Girlfiriend  gf=new Girlfiriend ();
  private Girlfiriend (){
  }
  public static Girlfiriend getGirlfriend(){
        return gf;  
}
}

饿汉模式什么都好,就是有点占地方,每次加载类的时候就存在了。有没有什么办法,用的时候在加载呢。没办法,世界是被懒人推动前进的,还真有。

懒汉模式:

public class Girlfiriend extends Friend{
  private static final Girlfiriend  gf;
  private Girlfiriend (){
  }
  public static synchronized Girlfiriend getGirlfriend(){
     if(gf==null){
        gf= new Girlfriend();
      }
        return gf;  
}
}

这种方法实现了在需要的时候加载。但是注意这里的synchronized关键字,synchronized 保证了当进行多线程操作的时候不会产生多个实例。但是这种做法有一个缺点,不管是不是已经存在实例了,都会被锁阻塞。
那么,有没有什么办法解决呢。这个世界是由聪明人改善,所以当然有!

当当当当,DCL模式来了。DCL是不是听起来特别高大上,其实就是Double Check Lock,说人话就是,你瞅两次看看到底有没。

public class Girlfiriend extends Friend{
  private static final Girlfiriend  gf;
  private Girlfiriend (){
  }
  public static  Girlfiriend getGirlfriend(){
     if(gf==null){
        synchronized(Girlfriend.class){
            if(gf==null){
              gf= new Girlfriend();
            }
        }
      }
        return gf;  
}
}

是不是感觉这就结束了。一篇好的文章是要出其不意的。所以,没完。
DCL并不是十分稳定的,由于java编译器允许处理器乱序执行,所以这样做是有隐患的。
简单说,其实new对象的操作不是原子性的。这句代码最终会被编译成多条汇编指令。
(1)给Girlfriend的实例分配内存
(2)调用Girlfriend()的构造函数,初始化成员字段
(3)将gf对象指向分配的内存空间
也就是说这三条指令顺序是不可预知的。当另一个线程执行第一个if(gf==null)的时候,由于已经调用了构造函数,但是构造还没有完成。会把没有构造完全的对象返回。
那么怎么解决呢,聪明的你一定也能想到,只不过聪明人太多,有人先想到了:
静态内部类单例模式:

public class Girlfiriend extends Friend{
  private Girlfiriend (){
  }
  public static Girlfiriend getGirlfriend(){
        return GirlfriendMother.gf;  
}
private static class GirlfriendMother{
        private static final Girlfiriend gf= new Girlfiriend ();
}
}

第一次加载Girlfriend的时候,gf不会被初始化,(java类只有被调用的时候才会初始化)。这种方式不仅能够确保线程的安全,也能够保证单例对象的唯一性,同时也延迟了单例的实例化。所以这才是推荐使用的单例模式实现的方式。

嘿嘿,你以为到这就完了?too young too naive:
最后是一种单例模式的终极形态——枚举单例:

public enum Girlfriend{
GIRLFRIEND;
}

默认枚举实例的创建是线程安全的,并且在任何情况下它都是一个单例。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 单例模式(SingletonPattern)一般被认为是最简单、最易理解的设计模式,也因为它的简洁易懂,是项目中最...
    成热了阅读 4,298评论 4 34
  • 前言 本文主要参考 那些年,我们一起写过的“单例模式”。 何为单例模式? 顾名思义,单例模式就是保证一个类仅有一个...
    tandeneck阅读 2,540评论 1 8
  • 一.什么是单例模式 单例模式的定义:确保一个类只有一个实例,并提供一个访问他的全局访问点。单例模式是几个设计模式中...
    Geeks_Liu阅读 2,247评论 0 10
  • 1.单例模式概述 (1)引言 单例模式是应用最广的模式之一,也是23种设计模式中最基本的一个。本文旨在总结通过Ja...
    曹丰斌阅读 3,006评论 6 47
  • 生活是用来热爱的,不是用来等待的。过好每个瞬间,也就能过好这一生。 懂很多道理,不如珍惜生命的中的小确幸,小确幸积...
    小李非刀阅读 6,405评论 69 180