iOS單例模式

1. 利用@synchronized創(chuàng)建單例

@implementation Singleton

+ (instancetype)shareInstance
{
    static Singleton* single;
    @synchronized(self){
        if (!single) {
            single = [[Singleton alloc] init];
        }
    }
    return single;
}

@end

ps:嚴(yán)格意義上來說,我們還需要將alloc方法封住,因?yàn)閲?yán)格的單例是不允許再創(chuàng)建其他實(shí)例的,而alloc方法可以在外部任意生成實(shí)例。但是考慮到alloc屬于NSObject,iOS中無法將alloc變成私有方法,最多只能覆蓋alloc讓其返回空,不過這樣做也可能會(huì)讓使用接口的人誤解,造成其他問題。所以我們一般情況下對alloc不做特殊處理。系統(tǒng)的單例也未對alloc做任何處理

2. 利用dispatch_once創(chuàng)建單例

使用@synchronized雖然解決了多線程的問題,但是并不完美。因?yàn)橹挥性趕ingle未創(chuàng)建時(shí),我們加鎖才是有必要的。如果single已經(jīng)創(chuàng)建.這時(shí)候鎖不僅沒有好處,而且還會(huì)影響到程序執(zhí)行的性能(多個(gè)線程執(zhí)行@synchronized中的代碼時(shí),只有一個(gè)線程執(zhí)行,其他線程需要等待)。那么有沒有方法既可以解決問題,又不影響性能呢?
這個(gè)方法就是GCD中的dispatch_once

+ (instancetype)sharedInstance {
    static dispatch_once_t once;
    static id sharedInstance;
    dispatch_once(&once, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}

2.1 dispatch_once原理

dispatch_once為什么能做到既解決同步多線程問題又不影響性能呢?
下面我們來看看dispatch_once的原理:
dispatch_once主要是根據(jù)onceToken的值來決定怎么去執(zhí)行代碼。

  1. 當(dāng)onceToken = 0時(shí),線程執(zhí)行dispatch_once的block中代碼
  2. 當(dāng)onceToken = -1時(shí),線程跳過dispatch_once的block中代碼不執(zhí)行
  3. 當(dāng)onceToken為其他值時(shí),線程被線程被阻塞,等待onceToken值改變

當(dāng)線程首先調(diào)用shareInstance,某一線程要執(zhí)行block中的代碼時(shí),首先需要改變onceToken的值,再去執(zhí)行block中的代碼。這里onceToken的值變?yōu)榱?40734731430192。
這樣當(dāng)其他線程再獲取onceToken的值時(shí),值已經(jīng)變?yōu)?40734731430192。其他線程被阻塞。
當(dāng)block線程執(zhí)行完block之后。onceToken變?yōu)?1。其他線程不再阻塞,跳過block。
下次再調(diào)用shareInstance時(shí),block已經(jīng)為-1。直接跳過block。
這樣dispatch_once在首次調(diào)用時(shí)同步阻塞線程,生成單例之后,不再阻塞線程。dispatch_once是創(chuàng)建單例的最優(yōu)方案

參考

作者:左忠飛
鏈接:https://juejin.cn/post/6844903784100233230

iOS 單例模式: http://www.itdecent.cn/p/a92c0283f243

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容