再談 Singleton

我們現在用 Objective-C 實作 Singleton 的時候,大概都是按照 Mike Ash 的建議—參見 Friday Q&A 2009-10-02: Care and Feeding of Singletons─使用 GCD 裡頭的 dispatch_once 實作。大概像這樣:

@interface MyClass : NSObject
+ (instancetype) sharedInstance;
@end

@implementation MyClass

+ (instancetype) sharedInstance
{
    static MyClass *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[MyClass alloc] init];
    });
    return instance;
}
@end

之所以這麼寫的原因,是為了避免在多重 thread 的環境下,shared instance 可能會被重複建立的問題。我們來看如果只用 if 語法實作的 singleton:

@implementation MyClass
+ (instancetype) sharedInstance
{
    static MyClass *instance = nil;
    if (!instance) {
        instance = [[MyClass alloc] init];
    }
    return instance;
}
@end

在 instance 這個變數還沒有建立的狀況下,假如就已經有多個 thread 同時進入了前面這段程式的 if 判斷式當中,那麼,每個進入這段程式的 thread,都會分別執行到 instance = [[MyClass alloc] init]; 這一行,而重複建立 instance。我們對於Singleton 物件的要求是:這個 Class 只會建立一個 instance,在所有地方呼叫 +sharedInstance,也都只該拿到同一個物件,但是在這種寫法中,不同 thread 呼叫 +sharedInstance,就可能會拿到不同的物件。

由於 dispatch_once 裡頭的 block 只會執行一次,我們便透過這個特性,保證 instance = [[MyClass alloc] init]; 只會被呼叫到一次。

相關閱讀

results matching ""

    No results matching ""