单例模式
2023-08-13 22:06 tonyniu8 阅读(10) 评论(0) 编辑 收藏 举报双重锁
解释
- 双重if是需要的。
如果只有一重,还是可能初始化两次 - valatile是要得。
uniqueInstance = new Singleton();
这段代码其实是分为三步执行:
- 为 uniqueInstance 分配内存空间
- 初始化 uniqueInstance
- 将 uniqueInstance 指向分配的内存地址
但是由于 JVM 具有指令重排的特性,执行顺序有可能变成 1>3>2。指令重排在单线程环境下不会出现问题,但是在多线程环境下会导致一个线程获得还没有初始化的实例。例如,线程 T1 执行了 1 和 3,此时 T2 调用 getUniqueInstance() 后发现 uniqueInstance 不为空,因此返回 uniqueInstance,但此时 uniqueInstance 还未被初始化。
使用 volatile 可以禁止 JVM 的指令重排,保证在多线程环境下也能正常运行。
if (uniqueInstance == null) {
synchronized (Singleton.class) {
uniqueInstance = new Singleton();
}
}
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton() {
}
public static Singleton getUniqueInstance() {
if (uniqueInstance == null) {
synchronized (Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
静态内部类
//静态内部类加载时不会加载。
//只有调用时,才会调用。
//这种方式不仅具有延迟初始化的好处,由jvm只初始一个
package com.java.design.pattern;
//静态内部类
//由jvm只初始一个
public class Singleton1 {
private Singleton1(){}
private static class SingletonHolder{
private static final Singleton1 INSTANCE=new Singleton1();
}
public static Singleton1 getUniqueInstance(){
return SingletonHolder.INSTANCE;
}
}