定义:java
优势:数据库
缺点:设计模式
使用场景:安全
关键点:bash
public class Singleton {
private static Singleton singleton = null;
private Singleton(){
}
public static Singleton getInstance(){
if(singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
复制代码
若是两个线程同时执行到singleton == null 的判断的时候,两个线程条件都知足,会出现建立两个对象的状况,违反了单例只建立一个对象的原则。网络
public class Singleton {
private static Singleton singleton = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return singleton;
}
}
复制代码
public class Singleton {
private static Singleton singleton = null;
private Singleton(){
}
public synchronized static Singleton getInstance(){
if(singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
复制代码
public class Singleton {
private static volatile Singleton singleton = null;
private Singleton() {
}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
复制代码
singleton = new Singleton() 不是原子操做,这段代码会编译成多条指令
(1)将对象new出来,给Singleton分配内存空间
(2)调用Singleton构造函数,初始化成员变量
(3)将singleton指向分配的内存,此时singleton就不为空了
java编译器容许指令乱序执行,因此二、3步执行顺序没法保证,就可能线程B执行了这段代码,singleton指向了内存空间,可是成员变量还没初始化完。此时若是线程A经过singleton== null进行判断,发现对象不为空,拿对象去使用,可是成员变量还没初始化完,就会出错。多线程
被volatile关键字修饰,可以保证内存可见性和禁止进行指令重排序,经过该特性保证了singleton = new Singleton()的指令执行顺序函数
public class Singleton {
private Singleton() {
}
private static class SingletonInner {
private static final Singleton sInstance = new Singleton();
}
public static Singleton getInstance() {
return SingletonInner.sInstance;
}
}
复制代码
public enum Singleton{
SINGLETON;
}
复制代码
private Object readResolve() throws ObjectStreamException {
return sInstance;
}
复制代码
参考资料:优化