设计模式6-单例模式与多线程初始化

package DesignPattern;

public class SingletonPattern {
    //单线程传统单例模式,此种模式在多线程模式下不适用
    public static class TraditionSingleton{
        private TraditionSingleton(){}//禁用实例化对象,不允许创建多个实例对象

        private static TraditionSingleton uniqueInstance;
        public static TraditionSingleton getInstance(){//延迟实例化
            if(uniqueInstance==null){
                uniqueInstance= new TraditionSingleton();
            }
            return uniqueInstance;
        }
    }
    //多线程单例模式
    //1.添加同步,但是会降低效率(延迟初始化
    public static class Singleton1{
        private Singleton1(){}
        private static Singleton1 uniqueInstance;
        public synchronized static Singleton1 getInstance(){
            if(uniqueInstance==null){
                uniqueInstance= new Singleton1();
            }
            return uniqueInstance;
        }
    }
    //2.双重检查锁定(常见错误)(延迟初始化
    public static class Singleton2{
        private Singleton2(){}
        private static Singleton2 uniqueInstance;
        public static Singleton2 getInstance(){
            if(uniqueInstance==null){
                synchronized (Singleton2.class){
                    if(uniqueInstance==null)
                        uniqueInstance=new Singleton2();
                }
            }
            return uniqueInstance;
        }
    }
    /*
    双重检查锁定的问题:
    uniqueInstance=new Singleton2();
    可以分解为:
    memory = allocate();    //1分配内存空间
    ctorInstance(memory);   //2初始化对象
    instance=memory;        //3设置instance指向刚初始化的对象
    由于指令重派的问题,编译器或者系统可能将赋值语句排到初始化语句前,如果,另外一个线程在赋值语句后,
    初始化语句前访问了该引用,此时会出现nullpoint问题
     */
    //3.类初始化锁,把同步交给JVM
    //(1)急切初始化
    public static class Singleton31{
        private Singleton31(){}
        private static Singleton31 uniqueInstance= new Singleton31();
        public static Singleton31 getInstance(){
            return uniqueInstance;
        }
    }
    //(2)延迟初始化
    public static class Singleton32{
        private Singleton32(){}
        private static class InstanceHolder{
            public static Singleton32 uniqueInstance=new Singleton32();
        }
        public static Singleton32 getInstance(){
            return InstanceHolder.uniqueInstance;
        }
    }
    /*
    原理:允许初始化中23的重排序,但是不允许非构造线程看到这个重排序,利用JVM对类的初始化过程的同步
    首先从JVM中获取InstanceHolder初始化锁的线程,负责初始化过程,其他线程看不见这个初始化过程
    缺点:只能对静态字段延迟初始化
     */

    //4.使用volatile(延迟初始化
    public static class Singleton4{
        private Singleton4(){}
        private volatile static Singleton4 uniqueInstance;
        public static Singleton4 getInstance(){
            if(uniqueInstance==null){
                synchronized (Singleton4.class){
                    if(uniqueInstance==null)
                        uniqueInstance=new Singleton4();
                }
            }
            return uniqueInstance;
        }
    }
    /*
    volatile语义 重写uniqueInstance内容前的所有读写操作(包括volatile读写和普通读写)不能重排序,
    因此禁止了初始化语句和赋值语句的重排序
     */
}

posted @ 2019-04-17 16:25  Fake_coder  阅读(245)  评论(0编辑  收藏  举报