單例模式的優缺點


單例模式的優缺點

1、時間和空間

比較上面兩種寫法:懶漢式是典型的時間換空間,也就是每次獲取實例都會進行判斷,看是否需要創建實例,浪費判斷的時間。當然,如果一直沒有人使用的話,那就不會創建實例,則節約內存空間。

餓漢式是典型的空間換時間,當類裝載的時候就會創建類實例,不管你用不用,先創建出來,然后每次調用的時候,就不需要再判斷了,節省了運行時間。

2、線程安全

(1)從線程安全性上講,不加同步的懶漢式是線程不安全的,比如,有兩個線程,一個是線程A,一個是線程B,它們同時調用getInstance方法,那就可能導致並發問題。如下示例:

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

程序繼續運行,兩個線程都向前走了一步,如下:

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

(2)餓漢式是線程安全的,因為虛擬機保證只會裝載一次,在裝載類的時候是不會發生並發的。

(3)如何實現懶漢式的線程安全呢?

當然懶漢式也是可以實現線程安全的,只要加上synchronized即可,如下:

  1. public static synchronized Singleton getInstance(){} 

但是這樣一來,會降低整個訪問的速度,而且每次都要判斷。那么有沒有更好的方式來實現呢?

(4)雙重檢查加鎖

可以使用"雙重檢查加鎖"的方式來實現,就可以既實現線程安全,又能夠使性能不受到很大的影響。那么什么是"雙重檢查加鎖"機制呢?

所謂雙重檢查加鎖機制,指的是:並不是每次進入getInstance方法都需要同步,而是先不同步,進入方法過后,先檢查實例是否存在,如果不存 在才進入下面的同步塊,這是第一重檢查。進入同步塊過后,再次檢查實例是否存在,如果不存在,就在同步的情況下創建一個實例,這是第二重檢查。這樣一來, 就只需要同步一次了,從而減少了多次在同步情況下進行判斷所浪費的時間。

雙重檢查加鎖機制的實現會使用一個關鍵字volatile,它的意思是:被volatile修飾的變量的值,將不會被本地線程緩存,所有對該變量的讀寫都是直接操作共享內存,從而確保多個線程能正確的處理該變量。

看看代碼可能會更加清楚些。示例代碼如下:

    public class Singleton {  
        /**  
         * 對保存實例的變量添加volatile的修飾  
         */  
        private volatile static Singleton instance = null;  
        private Singleton(){  
        }  
        public static  Singleton getInstance(){  
            //先檢查實例是否存在,如果不存在才進入下面的同步塊  
            if(instance == null){  
                //同步塊,線程安全地創建實例  
                synchronized(Singleton.class){  
                    //再次檢查實例是否存在,如果不存在才真正地創建實例  
                    if(instance == null){  
                        instance = new Singleton();  
                    }  
                }  
            }  
            return instance;  
        }  
    } 

 

這種實現方式可以實現既線程安全地創建實例,而又不會對性能造成太大的影響。它只是在第一次創建實例的時候同步,以后就不需要同步了,從而加快了運行速度。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM