IOS 單例模式筆記

這裏不講單例模式的用途了,下面的代碼,主要都會在.m文件的代碼。
多線程

#import "SingletonClass.h"

@implementation SingletonClass

+ (SingletonClass *)shareSingletonClass {
    SingletonClass* singleton = [[SingletonClass alloc] init];
    return singleton;
}

@end

這裏定義了一個類方法shareSingletonClass,這個單例類會調用這個方法獲得全局惟一實例,但顯然如今還達不到生成全局惟一實例的效果,每次調用這個方法都會生成一個新的實例。併發

再次修改:
高併發

#import "SingletonClass.h"

static SingletonClass* singleton = nil;

@implementation SingletonClass

+ (SingletonClass *)shareSingletonClass {
    
    if (singleton == nil) {
        singleton = [[SingletonClass alloc] init];
    }
    
    return singleton;
}

@end

這裏生成了一個靜態的SingletonClass實例,而後判斷若是這個實例沒有被建立,就建立,不然直接返回這個實例。
性能

但這種作法只適合單線程,多線程的狀況下,各個線程在最開始都會判斷到singleton=nil,會生成多個singleton實例。因此這時候須要線程鎖:優化

+ (SingletonClass *)shareSingletonClass {
    
    @synchronized(self) {
        if (singleton == nil) {
            singleton = [[SingletonClass alloc] init];
        }
    }
    
    return singleton;
}

這樣子已經完成一個單例了。
spa

可是在有高併發線程的狀況下,每次都要作if判斷,是很耗性能的,在線程鎖裏面的代碼,是越少越好,而咱們真正所須要的是singleton = [[SingletonClass alloc] init];這句代碼,因此能夠把線程鎖移到if判斷裏面。線程

+ (SingletonClass *)shareSingletonClass
{
    
    if (singleton == nil) {
        @synchronized(self) {
            singleton = [[SingletonClass alloc] init];
        }
    }
    
    return singleton;
}

但這樣在多線程下,新線程仍是會近到線程鎖裏面,生成新的實例,因此仍是要再作一層判斷:
code

+ (SingletonClass *)shareSingletonClass
{
    
    if (singleton == nil) {
        @synchronized(self) {
            if (singleton == nil) {
                singleton = [[SingletonClass alloc] init];
            }
        }
    }
    
    return singleton;
}

第一個if判斷,使得只有在實例沒被建立後,纔會進到線程鎖裏面,減小進入線程鎖判斷;第二個判斷,是多線程的時候的判斷,進到這裏的概率已經少了不少了。這種是多層線程鎖。
it


事實上,在OBJC裏面,對於單例,已經爲咱們準備好了方法:io

+ (SingletonClass *)shareSingletonClass
{
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        singleton = [[SingletonClass alloc] init];
    });
    
    return singleton;
}

系統的方法,通常是被優化到最佳的,因此推薦使用這種方法。

相關文章
相關標籤/搜索