// 一般写法
public class Singleton
{
private volatile static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
// 双重检查
synchronized (Singleton.class)
{
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
// 静态内部类方法
public class Singleton{
private static class SingletonHolder{
private static final Singleton INSTANCE = new Singleton();
}
private Singleton(){}
public static Singleton getInstance(){
return SingletonHolder.INSTANCE;
}
}
// 枚举 不能反射
public enum Singleton {
INSTANCE;
public void whateverMethod() {}
}
volatile的汇编指令:
load addl;
volatile的两个特性:
1、保持线程可见性
一个线程修改了该被volatile修饰的变量,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,可以立即获取修改之后的值。
https://blog.csdn.net/weixin_38106322/article/details/105745555
https://blog.csdn.net/qq_36881887/article/details/105187989
2、禁止指令重排序
JVM给改变volatile变量指令的上下加了内存屏障。
new一个对象的步骤一般是:
1、首先在堆中分配一个内存或者地址
2、将对象中的所有数据类型初始化
3、然后赋值执行构造器
4、最后创建成功返回对象地址。
但是,可能由于JVM把字节码指令重排序,把赋值放在了return之后,导致先返回了地址后赋值。也就可能返回的是空的值。返回空就错了。