单例模式
是Java常用的一种设计模式,主要目的是为了确保一个类在整个系统中只有一个实例。
单例模式可以分为3种主要类型,懒汉式,饿汉式,登记式。
懒汉式
在类加载时不初始化,而是在第一次被使用时才初始化。
需要注意线程安全问题,双重检查。
java
/**
java 指令重排序:
在这个例子中,Singleton类使用双重检查锁定模式来确保instance字段只被初始化一次。在没有指令重排序的情况下,这个实现看起来是线程安全的。然而,由于Java内存模型和指令重排序的存在,这个实现可能会引发问题。
问题出在instance = new Singleton();这行代码上。这行代码实际上包含了三个操作:
1. 分配内存给Singleton对象。
2. 调用Singleton类的构造函数初始化对象。
3. 将instance字段指向新创建的对象。
由于指令重排序,这三个操作的实际执行顺序可能与上述顺序不同。例如,处理器可能先执行第3步,然后再执行第1步和第2步。在这种情况下,另一个线程可能会看到instance字段不为null,但实际上对象还没有完全初始化,从而导致不可预测的行为。
为了解决这个问题,可以将instance字段声明为volatile,以确保其初始化过程中的指令不会被重排序:
*/
public class Singleton {
private static volatile Singleton singleton = null;
private Singleton(){};
public Singleton getSingleton(){
if(null == singleton){ // 第一次检查
synchronized(Singleton.class){
if(null == singleton){ // 第二次检查
singleton = new Singleton();
}
}
}
return singleton;
}
}
饿汉式
在类加载时就完成了初始化,所以类加载比较慢,但获取对象的速度快。