手撕设计模式【深度解析懒汉式单例】

普通懒汉式单例

代码解析

public class Singleton {

    //私有化构造方法
    private Singleton(){}

    //volatile 禁止指令重排
    public volatile static Singleton singleton;

    //双重判定锁
    public static Singleton getSingleton() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    //不是原子性操作,存在指令重排。volatile 禁止指令重排
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }

    //测试结果  s1 和 s2 hashCode 相同,暂且表示单例成功
    public static void main(String[] args) {
        Singleton s1 = Singleton.getSingleton();
        Singleton s2 = Singleton.getSingleton();
        System.out.println(s1.hashCode());
        System.out.println(s2.hashCode());
    }
}

破坏这个单例

破坏测试代码

//测试使用反射破坏单例
    public static void main(String[] args) throws Exception {
        //正常获取单例
        Singleton s1 = Singleton.getSingleton();
        //反射获取单例
        Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        //通过反射创建对象
        Singleton s2 = constructor.newInstance();
        System.out.println("s1" + s1.hashCode());
        System.out.println("s2" + s2.hashCode());
    }

成功破坏单例

手撕设计模式【深度解析懒汉式单例】

高级懒汉式单例

代码解析

public class Singleton {

    //私有化构造方法
    private Singleton(){
        //判断是否已有实例存在
        if (singleton != null) {
            throw new RuntimeException("不要用反射试图破坏单例");
        }
    }

    //volatile 禁止指令重排
    public volatile static Singleton singleton;

    //双重判定锁
    public static Singleton getSingleton() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    //不是原子性操作,存在指令重排。volatile 禁止指令重排
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

测试结果

手撕设计模式【深度解析懒汉式单例】

再次破坏这个单例

破坏测试代码

 //测试全部使用反射破坏单例
    public static void main(String[] args) throws Exception {
        //反射获取单例
        Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        //通过反射创建对象
        Singleton s1 = constructor.newInstance();
        Singleton s2 = constructor.newInstance();
        System.out.println("s1----> " + s1.hashCode());
        System.out.println("s2----> " + s2.hashCode());
    }

手撕设计模式【深度解析懒汉式单例】

终极懒汉式单例

代码解析

public class Singleton {
    //设置信号灯,防止反射破坏单例
    private static boolean flag = false;
    //私有化构造方法
    private Singleton(){
        synchronized (Singleton.class) {
            if (!flag) {
                flag = true;
            }else {
                throw new RuntimeException("不要用反射试图破坏单例");
            }
        }
    }

    //volatile 禁止指令重排
    public volatile static Singleton singleton;

    //双重判定锁
    public static Singleton getSingleton() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    //不是原子性操作,存在指令重排。volatile 禁止指令重排
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }

    //测试全部使用反射破坏单例
    public static void main(String[] args) throws Exception {
        //反射获取单例
        Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        //通过反射创建对象
        Singleton s1 = constructor.newInstance();
        Singleton s2 = constructor.newInstance();
        System.out.println("s1----> " + s1.hashCode());
        System.out.println("s2----> " + s2.hashCode());
    }
}

测试结果

手撕设计模式【深度解析懒汉式单例】

成功实现单例模式

上一篇:SpringBoot学习笔记(一)


下一篇:2021-07-12 内部类和单例模式