再谈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 ""