单例模式与多线程

1. 饿汉模式

  也称立即加载模式,指使用类的时候已经将对象创建完毕。

public class hungerSingleton {
    private static hungerSingleton hungerSingleton = new hungerSingleton();
    private hungerSingleton(){

    }
    public static hungerSingleton getInstance(){   //静态,不用同步(类加载时已初始化,不会有多线程的问题)
        return hungerSingleton;
    }
}

 

2. 懒汉模式

  也称延迟加载模式,指调用get()方法时实例才被工厂创建。

public class lazySingleton {
    private static lazySingleton lazy = null;
    private lazySingleton(){

    }
    public static synchronized lazySingleton getInstance(){   //保证线程安全(因为类变量不是在加载时初始化的)
        if (lazy == null)
            lazy = new lazySingleton();
        return lazy;
    }
}

3. 双重校验锁实现单例模式

public class MySingleton {
    private volatile static MySingleton mySingleton;
    private MySingleton(){

    }
    public static MySingleton getUniqueInstance(){
        if (mySingleton == null){
            synchronized (MySingleton.class){
                if(mySingleton == null)
                    mySingleton = new MySingleton();
            }
        }
        return mySingleton;
    }
}

  使用volatile修改变量mySingleton使该变量在多个线程间达到可见性,此外也禁止了mySingleton = new MySingleton()代码重排序

  该代码分为3个步骤:

  1. memory = allocate();          //分配对象的内存空间
  2. ctorInstance(memory) ;   //初始化对象
  3. mySingleton = memory;  //设置instance指向刚分配的内存地址

  JIT有可能将这3个步骤重排序成:

  1. memory = allocate();          //分配对象的内存空间
  2. mySingleton = memory;  //设置instance指向刚分配的内存地址
  3. ctorInstance(memory) ;   //初始化对象

  这时就会出现以下情况:虽然构造方法还没执行,但mySingleton对象具有了内存地址,值不为null,当访问mySingleton对象中的变量时还是默认值。

posted @ 2021-08-09 23:33  明羽1  阅读(44)  评论(0)    收藏  举报