單例模式中可能存在的一些問題(執行緒安全問題)

魏大大i發表於2018-05-09

單例的設計模式中,一些程式碼的寫法會存線上程安全的問題,舉例如下:

(1)單例模式的懶漢式[執行緒不安全,不可用]

    public class Singleton {  
      
        private static Singleton instance=null;  
          
        private Singleton() {};  
          
        public static Singleton getInstance(){  
              
            if(instance==null){  
                instance=new Singleton();  
            }  
            return instance;  
        }  
    }  

這種方式是在呼叫getInstance方法的時候才建立物件的,所以它就被稱為懶漢模式。

這是存線上程安全問題的,那具體是存在怎樣的執行緒安全問題?怎樣導致這種問題的?好,我們來說一下什麼情況下這種寫法會有問題。在執行過程中可能存在這麼一種情況:多個執行緒去呼叫getInstance方法來獲取Singleton的例項,那麼就有可能發生這樣一種情況,當第一個執行緒在執行if(instance==null)時,此時instance是為null的進入語句。在還沒有執行instance=new Singleton()時(此時instance是為null的)第二個執行緒也進入了if(instance==null)這個語句,因為之前進入這個語句的執行緒中還沒有執行instance=new Singleton(),所以它會執行instance = new Singleton()來例項化Singleton物件,因為第二個執行緒也進入了if語句所以它會例項化Singleton物件。這樣就導致了例項化了兩個Singleton物件。所以單例模式的懶漢式是存線上程安全的,既然它存在問題,那麼可能有解決辦法,於是就有下面加鎖這種寫法。

(2)懶漢式執行緒安全的[執行緒安全,效率低不推薦使用]

public class Singleton {  
  
    private static Singleton instance=null;  
      
    private Singleton() {};  
      
    public static synchronized Singleton getInstance(){  
          
        if(instance==null){  
            instance=new Singleton();  
        }  
        return instance;  
    }  
} 

缺點:效率太低了,每個執行緒在想獲得類的例項的時候,執行getInstance()方法都要進行同步。而其實這個方法只執行一次例項化程式碼就夠了,後面想獲得該例項,直接return就行了。方法進行同步效率太低要改進。

(3)單例模式懶漢式[執行緒不安全,不可用]

public class Singleton7 {  
  
    private static Singleton instance=null;  
      
    public static Singleton getInstance() {  
        if (instance == null) {  
            synchronized (Singleton.class) {  
                instance = new Singleton();  
            }  
        }  
        return instance;  
    }  
}

這種寫法也是不安全的,當一個執行緒還沒有例項化Singleton時另一個執行緒執行到if(instance == null)這個判斷時語句機會進入if語句,雖然加了鎖,但是等到第一個執行緒執行完instance=new Singleton()跳出這個鎖時,另一個進入if語句的執行緒同樣會例項化另外一個SIngleton物件。因為這種改進方法不可行。

總結:

以上就是單例模式中,會引發的執行緒安全問題了

相關文章