Reputation: 77596
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;
}
Upvotes: 5
Views: 8407
Reputation: 86651
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;
}
Upvotes: 8
Reputation: 170
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.
Upvotes: -1
Reputation: 107754
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;
}
Upvotes: 9
Reputation: 28688
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
Upvotes: 10