【问题标题】:Whats the equivalent of synchronized in Objective-C?Objective-C 中同步的等价物是什么?
【发布时间】:2010-11-02 02:03:15
【问题描述】:

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

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

【问题讨论】:

标签: java objective-c singleton synchronized


【解决方案1】:

Obj-C 有一个同步结构

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

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

【讨论】:

  • 只是一个小修复,我认为OP想使用静态方法
【解决方案2】:

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

static MyObject *singleton = nil;

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

- (MyObject&)getSharedObject
{
  return singleton;
}

【讨论】:

  • 在单例类上同步,然后没有奇怪的竞争条件。
  • 这是苹果推荐的风格。
【解决方案3】:

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

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

注意事项:

  • 我已将其设为类方法。您实际上不必这样做,它可以作为实例方法工作。

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

  • 我已将退货放在@synchronize 块之外。从块内部返回是完全可以的,但如果你这样做了,你会收到一个虚假的 clang 静态分析器警告,说该方法可能不会返回值。


编辑

上述模式早已过时。最好使用dispatch_once 模式

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

    dispatch_once (&onceToken, ^{
        singleton = [[MyObject alloc] init];
    });
    return singleton;
}

【讨论】:

  • 静态 MyObject* 单例 = nil;这不是将单例对象设置为 nil,并在每次调用方法时重新实例化它吗?
  • IIRC,在 ObjC 中,static 基本上意味着“其中只有一个存在”因此,它只初始化一次。
  • Obj-C中的Static和C中的一样,意味着该行只会被初始化一次
  • 你也可以说MyObject.class代替[MyObject class]
  • @ToddLehman 我不确定点表示法是否适用于类属性。无论如何,我一直不喜欢 Objective-C 中的点符号。
【解决方案4】:

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

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

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

【讨论】:

  • 双重检查锁定涉及许多微妙的可能竞争条件。我会避免它。
  • 感谢您的反馈 JeremyP,我承认我不知道这些问题。但是,我仍然认为值得努力理解这些问题并正确处理,特别是如果此代码将是高流量,那么故意添加可能的争用点将太糟糕了。非常感谢!
  • 不用担心选票。我们在这里互相学习。
猜你喜欢
  • 2014-07-28
  • 2013-12-01
  • 2015-07-30
  • 2011-07-21
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 2018-04-19
  • 2010-10-24
相关资源
最近更新 更多