public class Main { private static Main instance = null; private Main() {} public static Main getInstance() { if(null == instance) instance = new Main(); return instance; } }
就是改进了check-then-act的原子性问题java
public class Main { private static Main instance = null; private Main() {} public static Main getInstance() { synchronized(Main.class) { if(null == instance) instance = new Main(); } return instance; } }
public class Main { private static Main instance = null; private Main() {} public static Main getInstance() { if(null == instance) synchronized(Main.class) { if(null == instance) instance = new Main(); // 问题出如今初始化 } return instance; } }
注意可见性是正确的,错误在于初始化的重排序多线程
上一篇文章已经写了3个步骤,一个线程在判断第一个if的时候可能另外一个线程执行到第二个步骤就写入引用了,这时返回的是默认值线程
既然重排序有问题那固然要volatilecode
public class Main { private static volatile Main instance = null; private Main() {} public static Main getInstance() { if(null == instance) synchronized(Main.class) { if(null == instance) instance = new Main(); } return instance; } }
利用class文件对于内部类的特性,实现上够简单排序
public class Main { private static class InstanceHolder { final static Main INSTANCE = new Main(); } public static Main getInstance() { return InstanceHolder.INSTANCE; } }
仅访问Singleton自己不会使Singleton.INSTANCE初始化内存
public enum Singleton { INSTANCE; Singleton() {} public void doSomething() {} } public class Main { public static void main() { new Thread() { public void run() { Singleton.INSTANCE.doSomething(); } }.start(); } }
补充一下奇怪的术语:懒汉式、饿汉式get
其中懒汉式就是带Lazy加载的意思,好比一、2class
而饿汉式我并不太清楚字面上的意思。。应该是指内存宽裕吧。。就是static直接返回的那种,显然不如静态内部类序列化
public class Main { private static Main instance = new Main(); private Main() {} public static Main getInstance() { return instance; } }
改进方法就是在构造方法建立保护null的判断引用
解决方法是重写readResolve()
方法,使得它在方法内直接返回instance