C# 多線程下的單例模式


在上一篇博客中(https://www.cnblogs.com/t140603/p/10318228.html)提到的第二個單例模式的實例為:

public class SingLetonClass

    {

        //定義一個用於保存靜態變量的實例

        private static SingLetonClass instance = null;

        //定義一個保證線程同步的標識

        private static readonly object locker = new object();

        //構造函數為私有,使外界不能創建該類的實例

        private SingLetonClass()

        {

        }

        public static SingLetonClass GetInstance()

        {

                lock (locker)

                {

                    if (instance == null)

                    {

                        SingLetonClass instance = new SingLetonClass();

                    }

                }

            return instance;

        }

    }

然而這個實現方式雖然是安全的,但是是不是最好的呢,還能不能再次進行優化?

下面就分析一下多線程中單例模式的運行:

  當程序的線程執行到鎖時,就會停下來判斷是否有其他線程在執行鎖里面的代碼,沒有才會進入繼續執行,那么如果多條線程同時運行到鎖的時候就只能一條一條進入鎖,進入並判斷是否已被實例化,如有就跳出,如無,則進行實例化。

  上面,我們對多線程中的單例模式進行了分析,從分析中我們可以看出,每條線程都要先進入鎖才做判斷,但在沒進入之前,線程就已經可以判斷出是否有過實例,那為什么我們不在外面就先進行判斷再進入鎖呢?下面就給出優化后的代碼:即再鎖的外面多加一次判斷。

public class SingLetonClass

    {

        //定義一個用於保存靜態變量的實例

        private static SingLetonClass instance = null;

        //定義一個保證線程同步的標識

        private static readonly object locker = new object();

        //構造函數為私有,使外界不能創建該類的實例

        private SingLetonClass()

        {

        }

        public static SingLetonClass GetInstance()

        {

            if (instance == null)

              {

                lock (locker)

                {

                    if (instance == null)

                    {

                        SingLetonClass instance = new SingLetonClass();

                    }

                }

            return instance;

          }

        }

}

  從更改后的代碼上來看,用了兩個if進行判斷的原因還是在於多線程的特性,還是因為多線程訪問函數時都是獨立訪問的,所以才要用到兩個if(如果對多線程特性不太了解的童鞋,可自行查資料研究一下)。

  先分析內層的if語句塊,在這個語句塊執行之前,先進行了加鎖操作,從而保證只有一個線程能夠訪問該語句塊,也就是保證只創建了一個實例。再分析外層的if語句塊,這使得每個線程欲獲取實例時不必每次都得加鎖,因為只有實例為空時(即需要創建一個實例),才需加鎖創建,若果已存在一個實例,就直接返回該實例,這樣就節省了性能開銷。

  這個過程實際上不是雙重鎖,只是進行了兩次判斷,因為真正的鎖機制代價是比較高的,所以本文介紹的機制可以稱為雙檢鎖機制。

 


免責聲明!

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



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