iOS線程安全單例詳解

只能生成一個實例的類是實現了Singleton模式的類型。由於設計模式在面向對象程序設計中起着舉足輕重的作用,在常用的模式中,singleton是唯一一個能夠用短短几十行代碼完整實現的模式。

 static PPLAccountManager *sharedInstance = nil;


1.最簡單(非線程安全)

+ (PPLAccountManager*)sharedManager {

    if (sharedInstance ==nil) {     

        sharedInstance = [[self alloc]init];  

    }    

    return sharedInstance;

 }

    單線程下運行正常,但是在多線程下就有問題了。如果兩個線程同時運行到判斷shareInstance是否爲nil的if語句,且shareInstance沒有創建時候,那麼2個線程都會創建一個實例,此時單例就不在滿足單例模式的要求了。爲了保證多線程環境下我們還是隻能得到類型的一個實例,需要加上一個同步鎖。如下:


2.線程安全(不是最優)

+ (PPLAccountManager*)sharedManager {

    @synchronized(self){    

      if (sharedInstance == nil) {            

          sharedInstance = [[selfalloc]init];        

      }        

      return sharedInstance;     

   }

 }

   這裏還不是很完美。我們還是設想兩個線程同時想創建一個實例,由於同一時刻只能有一個能得到同步鎖,每當第一個線程鎖加上鎖,第二個線程只能等待,當第一個線程發現實例還沒有創建時,它創建一個實例。接着第一個線程釋放同步鎖,此時第二個線程可以加上同步鎖,並運行接下來的 代碼。我們每次得到單例實例,都會試圖加上一個線程鎖,而加鎖是一個非常耗時的操作,在沒有必要的時候,我們儘量要避免。


3.線程安全(邏輯複雜)

+ (PPLAccountManager*)sharedManager { 

   if (sharedInstance == nil) {      

        @synchronized(self){   

            if (sharedInstance == nil) {      

                sharedInstance = [[self alloc]init];          

            }   

        }   

   }
   return sharedInstance;

 }

  這裏用了2個if判斷來提高效率,但是代碼實現邏輯比較複雜,容易出錯,我們還有更加優秀的的解法。


4.最優算法(官方推薦)

+ (PPLAccountManager*)sharedManager {


      static dispatch_once_t predicate;   

      dispatch_once(&predicate, ^{        

            sharedInstance = [[self allocinit];    });    

            return sharedInstance; 

      }  

 }



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章