實現cpu數據可見性, 禁止指令重排序java
當咱們寫出一個標準的雙重檢查鎖定單例模式時(以下), 代碼還是有問題的, 這是由於重排序的緣故,
線程有可能拿到還沒有實例化的對象的引用.
使用volatile修飾類變量, 禁止helloSingleton = new HelloSingleton()
這步的指令重排.程序員
private static HelloSingleton helloSingleton; public static HelloSingleton instance() { if (helloSingleton == null) { synchronized(SingletonFactory.class) { if (helloSingleton == null) { return helloSingleton = new HelloSingleton(); } } } return helloSingleton; }
還有一種更加優雅的方式, 使用內部類實現, 內部類會在被引用時才加載, 實現了懶加載編程
單例模式實現方式有好多種,但大部分都會有多線程環境下的問題;使用內部類能夠避免這個問題,由於在多線程環境下,jvm對一個類的初始化會作限制,同一時間只會容許一個線程去初始化一個類,這樣就從虛擬機層面避免了大部分單例實現的問題數組
public static class innerHolder { public static HelloSingleton helloSingleton = new HelloSingleton(); } public static HelloSingleton instanceV5() { return innerHolder.helloSingleton; }
什麼是Java內存模型多線程
雙重檢查鎖定併發