Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

making a class "thread safe" in iOS

I'm reading the Apple docs around Thread Safety, and it's not completely clear to me what (in practice) really constitutes a class being thread safe. To help understand this better, what would would all need to be done to the following class to make it thread safe (and why)?

#import "UnsafeQueue.h"

@interface UnsafeQueue()

@property (strong, nonatomic) NSMutableArray *data;

@end

@implementation UnsafeQueue

- (id)peek {
    return [self.data firstObject];
}

- (NSUInteger)length {
    return [self.data count];
}

- (void)enqueue:(id)datum {
    [self.data addObject:datum];
}

// other methods omitted...

@end

Would simply creating an ivar NSLock and then lock/unlock surrounding all interactions with the underlying NSMutableArray?

Does the length method, which is just asking for the array's count, need to do this as well?

like image 283
chinabuffet Avatar asked Jan 18 '15 00:01

chinabuffet


People also ask

How do I make a class object thread-safe?

To make these classes thread-safe, you must prevent concurrent access to the internal state of an instance by more than one thread. Because Java was designed with threads in mind, the language provides the synchronized modifier, which does just that.

How do you make a class thread-safe in Swift?

By creating a queue of tasks where only one task can be processed at any given time, you are indirectly introducing thread safety to the component that is using the queue. The greatest feature of DispatchQueue is how it completely manages any threading-related tasks like locking and prioritization for you.

What is IOS thread safety?

An object is said to be thread safe if more than one thread can call methods or access the object's member data without any issues; an "issue" broadly being defined as being a departure from the behaviour when only accessed from only one thread.

Is static thread-safe Ios?

No, static functions are not inherently thread-safe. Even your simple example isn't. Assuming both intvariable and stringvariable are supposed to be updated at the same time, another thread could observe the state of c1 between the two assignments, leading to data corruption.


1 Answers

The easiest and best way to make a class thread safe is to make it immutable. Then you don't have to deal with any of this. It just works. It really is worth your time to think about whether you need mutability on multiple threads.

But if an immutable class creates significant problems for your design, then generally the best way to implement it is with GCD rather than locks. GCD has much lower overhead and is generally speaking easier to get right.

In this particular case, I'd implement it along these lines (untested, and I've been working in Swift for a while now, so forgive me if I drop a semicolon):

#import "SafeQueue.h"

@interface SafeQueue()

@property (strong, nonatomic) NSMutableArray *data;
@property (strong, nonatomic) dispatch_queue_t dataQueue;

@end

@implementation SafeQueue

- (instancetype)init {
    if (self = [super init]) {
        _dataQueue = dispatch_queue_create("SafeQueue.data", DISPATCH_QUEUE_CONCURRENT);
    }
    return self;
}

- (id)peek {
    __block id result = nil;
    dispatch_sync(self.dataQueue, ^{ result = [self.data firstObject] });
    return result;
}

- (NSUInteger)length {
    __block NSUInteger result = 0;
    dispatch_sync(self.dataQueue, ^{ result = [self.data count] });
    return result;
}

- (void)enqueue:(id)datum {
    dispatch_barrier_async(self.dataQueue, ^{ [self.data addObject:datum] });
}

// other methods omitted...

@end

Note the use of dispatch_sync for all readers and dispatch_barrier_async for all writers. This is how you keep your overhead to a minimum by allowing parallel readers and exclusive writers. And if there is no contention (which is the normal case), dispatch_sync has much lower overhead than a lock (NSLock or @synchronized or even a pthreads lock).

See Migrating Away from Threads for more advice from Apple on how to better deal with concurrency in Cocoa.

like image 130
Rob Napier Avatar answered Oct 09 '22 02:10

Rob Napier