设计模式 -- 单例模式

166 阅读2分钟

「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战

设计模式 - 单例模式

含义: 保证一个类仅有一个实例,并提供一个访问它的全局访问点。

class Singleton{
    private static Singletion instance;
    
    //采用 private,防止实例化多个对象
    private Singleton(){
    }
    
    //为外界提供访问接口
    public static Singletion GetInstance(){
        if(instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}

但是在多线程中会出现同时访问 GetInstance() 方法的情况,仍然会 new 出多个 Singleton() 实例,这时候我还想使用单例模式要怎么办呢?

这时想到可以使用锁来规避这种情况.这里只列出了 synchronized 这种方法,当然你也可以使用 Lock 或者 Volatile来实现相同的方法。

class Singleton{
    private static Singletion instance;
    private Obgect lock = new Obgect();
    
    //采用 private,防止实例化多个对象
    private Singleton(){
    }
    
    //为外界提供访问接口
    public static Singletion GetInstance(){
        synchronized(lock){
            if(instance == null){
                instance = new Singleton();
            }
            return instance;
        }
    }
}

这种方法创建的Singleton() 实例是由第一次进入的线程进行创建的,所以之后的线程进入之后,并不需要在创建新的实例,从而在多线程中同时访问也不会创建出新的实例.

可是你一定觉得这样每次调用 GetInstance() 都会访问锁,使得多线程变成了单线程,影响性能。所以接下来看看下面的方法,只是做了一个小小的改动。

class Singleton{
    private static Singletion instance;
    
    //采用 private,防止实例化多个对象
    private Singleton(){
    }
    
    //为外界提供访问接口
    public static Singletion GetInstance(){
        if(instance == null){
            synchronized(lock){
                if(instance == null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

这样只有没有创建实例的时候进行加锁处理,有实例则会直接返回,不需要每次都对它进行加锁处理。不仅保证了仅仅创建一次实例,并且同时还保证里多线程的性能。当然了这么神奇又好用的方法也应该有一个自己的名字吧,它叫 Double-Check Locking(双重锁定),