5

目标c中java同步的等价物是什么?我希望能够使我的单例方法安全,因此当从 2 个不同的线程调用它时,他们会尝试一个一个地使用它。

+(MyObject*) getSharedObject
{
     if(!singleton)
     {
          singleton = [[MyObject alloc] init];
     }
     return singleton;
}
4

4 回答 4

10

Obj-C 有一个同步结构

-(MyObject*) getSharedObject
{
@synchronized(something)
{
     if(!singleton)
     {
          singleton = [[MyObject alloc] init];
     }
     return singleton;
}
}

从同步块中返回做“正确”的事情

于 2010-11-02T02:08:46.073 回答
9

Joshua 的回答是正确的,但要求您有一个要同步的对象。如果您不小心,对单例执行此操作可能会导致各种奇怪的竞争条件。单例的标准模式是在+initialize, using中初始化它dispatch_once,这样做是正确的:

static MyObject *singleton = nil;

+ (void)initialize {
  static dispatch_once_t pred;
  dispatch_once(&pred, ^{ singleton = [[MyObject alloc] init]; } );
}

- (MyObject&)getSharedObject
{
  return singleton;
}
于 2010-11-02T03:13:03.540 回答
8

为了同步单例创建,您应该使用单例的类作为要同步的对象。这是我通常的模式:

+(MyObject*) singleton
{
    static MyObject* singleton = nil;
    @synchronized([MyObject class])
    {
         if(singleton == nil)
         {
             singleton = [[MyObject alloc] init];
         }
    }
    return singleton;
}

注意事项:

  • 我已经把它变成了一个类方法。您实际上不必这样做,它将作为实例方法工作。

  • 通常在引用类时在类方法中使用self(或[self class]在实例方法中)。但是,这在这里是错误的,因为子类将使用与 MyObject 类不同的对象进行同步。

  • I have put the return outside of the @synchronize block. It is perfectly OK to return from inside the block, but if you do, you get a spurious clang static analyser warning saying the method might not return a value.


Edit

The above pattern is long since obsolete. It's best to use the dispatch_once pattern

+(MyObject*) singleton
{
    static dispatch_once_t onceToken;
    static MyObject* singleton = nil;

    dispatch_once (&onceToken, ^{
        singleton = [[MyObject alloc] init];
    });
    return singleton;
}
于 2010-11-02T10:15:13.030 回答
-1

我同意这两个答案。但是,如果想法是按需实例化,那么我会采用 Joshua 的建议,并使用双重检查锁定进行轻微修改:

if (!singleton)  
   @synchronized(something)  
      if (!singleton)  
         instantiate;

这样可以避免在对象实例化后不必要的锁定。

于 2010-11-02T05:37:39.813 回答