5

What is the equivalent of java synchronized in objective c? I want to be able to make my singleton method safe, so when it's bein called from 2 different threads, they try to use it 1 by 1.

+(MyObject*) getSharedObject
{
     if(!singleton)
     {
          singleton = [[MyObject alloc] init];
     }
     return singleton;
}
aryaxt
  • 76,198
  • 92
  • 293
  • 442

4 Answers4

10

Obj-C has a synchronized construct

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

returning from within a synchronized block does the 'right' thing

Joshua Weinberg
  • 28,598
  • 2
  • 97
  • 90
9

Joshua's answer is correct, but requires that you have an object on which to synchronize. Doing this for a singleton can lead to all sorts of odd race conditions if you're not careful. The standard pattern for a singleton is to initialize it in +initialize, using dispatch_once, which does the right thing:

static MyObject *singleton = nil;

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

- (MyObject&)getSharedObject
{
  return singleton;
}
Barry Wark
  • 107,306
  • 24
  • 181
  • 206
8

For synchronising singleton creation, you should use the singleton's class as the object to synchronise on. This is my usual pattern:

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

Points to note:

  • I've made it a class method. You don't actually have to, it'll work as an instance method.

  • Normally within class methods when referring to the class, you would use self (or [self class] in instance methods). However, that would be wrong here because subclasses would synchronise using a different object to the MyObject class.

  • 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;
}
JeremyP
  • 84,577
  • 15
  • 123
  • 161
  • 2
    static MyObject* singleton = nil; Doesn't this set the singleton object to nil, and re-instantiate it every time the method gets called? – aryaxt Nov 02 '10 at 17:28
  • IIRC, in ObjC, static basically means "only one of these exists" consequently, it's only initialized once. – JimR Nov 02 '10 at 18:49
  • 3
    Static in Obj-C is the same as it is in C, meaning that line will only be initialized once – Joshua Weinberg Nov 03 '10 at 01:34
  • You can also say `MyObject.class` in place of `[MyObject class]`. – Todd Lehman Mar 25 '16 at 23:39
  • @ToddLehman I'm not sure if dot notation works on class properties. In any case, I've always disliked dot notation in Objective-C. – JeremyP Mar 29 '16 at 10:11
  • While I am commenting on this fairly ancient answer, I'll point out that I don't use this pattern anymore, I use `dispatch_once`. – JeremyP Mar 29 '16 at 10:15
  • @JeremyP — Dot notation *does* work on class properties. I'm 100% certain about that. I do it all the time. I love dot notation in Objective-C. – Todd Lehman Mar 29 '16 at 13:49
  • It's the spawn of Satan in respect of Objective-C. If you want dots, use Swift. Actually, just use Swift anyway. – JeremyP Mar 30 '16 at 12:56
-1

I agree with both answers. But if the idea is to instantiate on demand then I'd go with Joshua's suggestion with a slight modification using double-checked-locking:

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

This way you avoid unnecessary locking after the object has been instantiated.

Barry Wark
  • 107,306
  • 24
  • 181
  • 206
fhj
  • 170
  • 2
  • 2
    There are many subtle possible race conditions involved with double checked locking. I'd avoid it. – JeremyP Nov 02 '10 at 10:26
  • I appreciate your feedback JeremyP, I admit I wasn't aware of such issues. However i still think it's worth the effort to understand those issues and get it right especially if this code is going to be high traffic, it will be too bad to knowingly add a possible point of contention. Much appreciated! – fhj Nov 03 '10 at 03:52
  • 1
    No worries about the votes. We're here to learn from each other. – fhj Nov 03 '10 at 03:57