单例模式与多线程
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个步骤:
- memory = allocate(); //分配对象的内存空间
- ctorInstance(memory) ; //初始化对象
- mySingleton = memory; //设置instance指向刚分配的内存地址
JIT有可能将这3个步骤重排序成:
- memory = allocate(); //分配对象的内存空间
- mySingleton = memory; //设置instance指向刚分配的内存地址
- ctorInstance(memory) ; //初始化对象
这时就会出现以下情况:虽然构造方法还没执行,但mySingleton对象具有了内存地址,值不为null,当访问mySingleton对象中的变量时还是默认值。
浙公网安备 33010602011771号