public class Singleton{
private static final Singleton instance = new Singleton();
private Singleton(){}
public Singleton getInstance(){
return instance;
}
}
饿汉式天生就是线程安全的,可以直接用于多线程而不会出现问题。
懒汉式
只有当第一次使用的时候,才会去初始化这个实例。
1.简单的实现
public class Singleton{
private static Singleton instance = null;
private Singleton(){}
public Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
public class Singleton{
private static Singleton instance = null;
private Singleton(){}
public Singleton getInstance(){
if(instance == null){
synchronized(Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
4.防止指令重排序
上面的双重检查锁定存在问题。instance() = new Singleton()这条语句在底层执行时有三个步骤,第1步是分配对象的内存空间,第2步是初始化对象,第3步是设置instance指向刚分配的内存地址。其中第2步和第3步可能发生重排序。如果线程A中发生了重排序,另一个并发执行的线程B有可能在进入getInstance()判断instance不为null。线程B接下来要访问instance所引用的对象,但此时这个对象可能还没有被A线程初始化!
当声明instance的引用为volatile后,指令重排序在多线程环境中就会被禁止。
public class Singleton{
private volatile static Singleton instance = null;
private Singleton(){}
public Singleton getInstance(){
if(instance == null){
synchronized(Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
public class Singleton{
private static class InstanceHolder{
public static Singleton instance = new Singleton();
}
private Singleton(){}
public static Instance getInstance(){
return InstanceHolder.instance;
}
}