Reputation: 404
Suppose if I want to implement both getter and setter I will do like this -
@interface Person () {
dispatch_queue_t _myConcurrentQueue;
}
@property (nonatomic, copy) NSString *personName;
@end
@implementation Person
- (instancetype)init
{
if (self = [super init])
{
_myConcurrentQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
}
return self;
}
@synthesize personName = _personName;
- (NSString *)personName {
__block NSString *tmp;
dispatch_sync(_myConcurrentQueue, ^{
tmp = _personName;
});
return tmp;
}
- (void)setpersonName:(NSString *)personName {
NSString* tmp = [personName copy];
dispatch_barrier_async(_myConcurrentQueue, ^{
_personName = tmp;
});
}
@end
But if I want to initialize my property lazily, then how can I make it thread safe? Example -
- (NSString *)personName {
If (!_personName) {
_personName = "Some Name"
}
return _personName;
}
What should I use serial queue with dispatch_async or concurrent queue with dispatch_async barrier and why?
Upvotes: 0
Views: 136
Reputation: 90571
Well, in your trivial case using a string literal (although you neglected the @
), there's little chance to go wrong.
However, for the general case where you initialize the instance variable in a more dynamic fashion with possible side effects, no, it's not thread-safe. Two threads can both be in the getter simultaneously. They can each submit a task to the queue. Since the queue is concurrent and neither task was submitted as a barrier, both tasks can run simultaneously. They might both test !_personName
and both determine that they need to initialize it. They will do redundant work and, if it has side effects, that could screw things up.
It's also possible that the compiler and/or CPU can re-order how things are done. One thread may think that _personName
is non-nil
and return the pointer, even though the other thread is still working on initializing the object. That is, the assignment to _personName
may happen before all of the effects of the expression on the right-hand side of the assignment have completed and are visible to the other thread.
Upvotes: 2