目标C中这两种线程安全初始化器的实现之间的区别

时间:2013-02-14 21:38:45

标签: ios objective-c thread-safety nspredicate synchronized

所以我有一个单例,我试图理解这两个实现之间的区别:在功能上我尝试用它们运行我的代码并且它们都工作

但是,我注意到在第一个实现中没有调用[self alloc]而是调用[super alloc]。我有点困惑。它似乎工作,但它似乎有点神奇,所以我想知道是否有人可以澄清

第一种方式:

 +(id)getSingleton
 {

    static dispatch_once_t pred;
    dispatch_once(&pred, ^{
    locMgrSingleton = [[super alloc] init];

        });

     return locMgrSingleton;

 }

另一种方式

 +(id)getSingleton
 {
     @synchronized(self)
     {
         if (locMgrSingleton == nil)
         {
             locMgrSingleton = [[self alloc]init];
             NSLog(@"Created a new locMgrSingleton");
         }
         else
        {
            NSLog(@"locMgrSingleton exists");
         }

     }

     return locMgrSingleton;
 }

3 个答案:

答案 0 :(得分:4)

使用[self alloc] vs [super alloc]没有区别,除非该类也覆盖+alloc。也就是说,应该调用[self alloc]。我敢打赌它正在调用super,因为这可能是从覆盖+alloc的实现改编而来的,以返回单例。

在任何情况下,selfsuper之外的两种模式之间的区别在我对this other question的回答中有所解释,但简而言之,dispatch_once()是现代的方式来做到这一点。它比@synchronized更快,并且具有更多的语义含义。

答案 1 :(得分:1)

如上所述http://cocoasamurai.blogspot.fi/2011/04/singletons-your-doing-them-wrong.htmldispatch_once电话似乎比@synchronized(self)稍快一些。

至于[super alloc]代替[self alloc]的原因,我认为没有任何理由可以将其专门适用于dispatch_once版本而不适用于self版本。在静态方法中,super只是引用类本身(以及[self alloc]到它的直接超类),我将其视为编写实际类名的简写,仅此而已。

我只使用过[super alloc],因为无论如何我都写了当前类的名字,而不是它的超类。不知道具体调用{{1}}是否具有任何特殊意义。

答案 2 :(得分:1)

在类方法中,self指向类本身。在您的两个实现中,[self alloc][MySingleton alloc][super alloc]在语义上都是等效的 - 除非您因某些奇怪的原因覆盖+alloc

您可能希望使用[super alloc]而不是其他原因的一个原因是当您使用编译器指令在声明中明确标记+alloc时:

+(instancetype) alloc __attribute__((unavailable("alloc not available")));

+(instancetype) alloc NS_UNAVAILABLE;

否则,当您尝试+alloc单例类的实例时,编译器将引发错误 - 除了当您+alloc共享单例实例时,您通常会想要这样做dispatch_once。