国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

objc單例的兩種安全實現方案

2019-11-14 20:12:16
字體:
來源:轉載
供稿:網友

所有轉出博客園,請您注明出處:http://m.survivalescaperooms.com/xiaobajiu/p/4122034.html

objc的單例的兩種安全實現方案

  首先應該知道單例的實現有兩大類,一個是懶漢式,一個是餓漢式。所謂的懶漢式就是在我們用到某對象(資源)的時候,去問一個負責提供的方法要那個對象。那個方法發現沒有這個資源時就去創建資源,如果是已經有該資源時就直接返回這個資源。而餓漢式就是那個負責提供的方法早已為我們準備好了我們想要的資源問它,它就提供給我們那個它早就準備好了的資源。

  餓漢式的實現是簡單而且好理解,但是它的理念不適合移動設備,因為餓漢式提前占用了內存,卻不管我們需不需要。所以餓漢式的實現在最后作為一點補充。我們主要使用懶漢式,它符合移動的開發理念。

首先理清實現單例模式(懶漢式)的思路:

  1.依靠什么來單例?

答:依靠靜態變量,因為它在內存中只有一份。只要判斷這個變量存不存在我們就知道需不需要創建一個對象賦值給那個靜態變量。

  2.但是在并發的情況下,我們同時去判斷一個變量都得到了nil的結果,這兩者就會都去創建一個新對象,那么會導致唯一性失效,就會使這兩次訪問得到不同的結果了,怎么解決?

答:加鎖或者使用dispatch_once。

 

  請先看加鎖的方案。多說兩句,加鎖@synchronized()的效率可不是java,c#那么高的。《cocao開發者編程手冊》47頁這樣寫道:“這需要精確的垃圾回收,以及重寫本地二進制文件的能力,Objectic-C編譯器這兩件事都做不了。所以,這個關鍵字非常低效”。但其實我們是可以避免頻繁加鎖,在網上找到的大多數代碼都沒有考慮到頻繁加鎖的問題的,而這里解決了這個問題,直接看代碼吧:

////  God.h#import <Foundation/Foundation.h>@interface God : NSObject<NSCopying>+ (God*)sharedGod;@end
////  God.m#import "God.h"static God *_singleGod;@implementation God+ (id)allocWithZone:(struct _NSZone *)zone{    if(!_singleGod){//防止頻繁加鎖        @synchronized([God class]){            if(!_singleGod)                _singleGod= [super allocWithZone:zone];        }    }    return _singleGod;}+ (God*)sharedGod{    if(!_singleGod){//防止頻繁加鎖        @synchronized([God class]){            if(!_singleGod){                _singleGod= [[self alloc] init];            }        }    }    return _singleGod;}- (id)copyWithZone:(NSZone *)zone{    return _singleGod;}//MRC下增加下面四個方法即可- (id)retain{    return self;}- (NSUInteger)retainCount{    return 1;}- (oneway void)release{}- (id)autorelease{    return self;}@end

加鎖的方案看起來似乎過于臃腫,使用GCD提供的dispatch_once來解決,將會使代碼看起來簡潔有力。(注:dispatch_once是GCD提供的一次性代碼方案,該方法在整個程序的生命周期中只會執行一次。下一次執行到這里不會再執行了。

dispatch_once版的實現如下:

////  God2.m#import "God2.h"static God2 *singleGod2;@implementation God2+ (id)allocWithZone:(struct _NSZone *)zone{    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        singleGod2= [super allocWithZone:zone];    });    return singleGod2;}+ (instancetype)sharedGod2{    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        singleGod2= [[self alloc] init];    });    return singleGod2;}- (id)copyWithZone:(NSZone *)zone{    return singleGod2;}//MRC下增加下面四個方法即可- (id)retain{    return self;}- (NSUInteger)retainCount{    return 1;}- (oneway void)release{}- (id)autorelease{    return self;}@end

使用dispatch_once來實現單例,我們更本不需要擔心線程安全問題,因為GCD提供的解決方案本身就是線程安全的。大大簡化了開發難度。

最后簡單的補充一點關于懶漢式的寫法,那么要知道+(void)load這個方法。它是類型加載到runtime時調用該方法,并且僅此一次。它的核心就是下面一行代碼:

+ (void)load{    singleGod3= [[self alloc] init];}

 歡迎各位朋友指正,以免誤人子弟。

 

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 宁明县| 桃源县| 资兴市| 泸定县| 青海省| 博乐市| 海南省| 芦溪县| 靖西县| 临猗县| 富民县| 蒲江县| 大竹县| 蓬莱市| 家居| 平南县| 日喀则市| 丁青县| 大厂| 郸城县| 湛江市| 中江县| 安丘市| 宝清县| 阿拉善盟| 集安市| 峡江县| 鹤山市| 水城县| 武威市| 上杭县| 镇宁| 天等县| 平潭县| 广平县| 雷波县| 平远县| 乳山市| 南投县| 繁昌县| 健康|