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