【地铁上的设计模式】--创建型模式:单例模式(三)--双重检验锁单例

2023-04-28 19:58:00 浏览数 (2)

什么是双重检验锁单例

双重检验锁单例模式实现了懒汉式单例模式的延迟加载和饿汉式单例模式的线程安全。其主要思路是在获取单例实例时,先检查是否已经实例化,如果没有才进行同步块。在同步块内部再进行一次实例化检查,以确保只有一个实例被创建。这样,就能够在保证单例实例唯一性的同时,减少了多线程环境下的性能开销。

如何实现双重检验锁单例

双重检验锁单例模式的实现步骤如下:

  1. 将构造函数设为私有,防止外部直接实例化该类;
  2. 声明一个静态的私有变量来保存类的唯一实例;
  3. 提供一个公有的静态方法获取类的唯一实例,在方法内部进行双重检验锁,即先判断实例是否已经创建,如果没有再进行同步块,在同步块内部再次检验实例是否已经被创建,如果没有则进行实例化。

Java实现

代码语言:javascript复制
public class Singleton {
    private volatile static Singleton instance;
    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

在示例中,我们使用了volatile关键字来保证线程间的可见性,同时在同步块内部进行双重检验锁,保证只有一个实例被创建。 C#实现

代码语言:javascript复制
public sealed class Singleton
{
    private static volatile Singleton instance;
    private static object syncRoot = new Object();

    private Singleton() {}

    public static Singleton Instance
    {
        get 
        {
            if (instance == null) 
            {
                lock (syncRoot) 
                {
                    if (instance == null) 
                    {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
}

在这个示例中,我们同样使用了volatile关键字来保证线程间的可见性,并在同步块内部进行双重检验锁,保证只有一个实例被创建。由于C#语言的特性,我们使用了lock关键字来进行同步,而不是synchronized关键字。

总结

双重检验锁单例模式能够确保只有一个实例被创建,并具有较好的性能表现和延迟创建的能力。其优点是在多线程环境下可以保证线程安全,并且可以延迟对象的创建,节省了系统资源。缺点是在某些情况下可能会出现线程安全问题,例如在JDK1.4之前的版本中使用双重检验锁时可能会因为指令重排而导致多线程下出现创建多个实例的问题。

0 人点赞