gpt4 book ai didi

ios - 在 iOS 中创建一个类 "thread safe"

转载 作者:技术小花猫 更新时间:2023-10-29 10:42:20 26 4
gpt4 key购买 nike

我正在阅读 Apple docs围绕线程安全,我并不完全清楚什么(在实践中)真正构成了一个线程安全的类。为了帮助更好地理解这一点,需要对以下类做些什么才能使其成为线程安全的(以及为什么)?

#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

是否会简单地创建一个 ivar NSLock,然后锁定/解锁周围 所有 与底层 NSMutableArray 的交互?

仅要求数组计数的长度方法是否也需要执行此操作?

最佳答案

使类线程安全的最简单和最好的方法是使其不可变。那么你不必处理任何这些。它只是工作。确实值得花时间考虑是否需要在多线程上实现可变性。

但是,如果不可变类给您的设计带来了重大问题,那么实现它的最佳方法通常是使用 GCD 而不是锁。 GCD 的开销要低得多,一般来说更容易正确。

在这种特殊情况下,我将按照以下方式实现它(未经测试,我已经在 Swift 中工作了一段时间,所以如果我省略了分号,请原谅我):

#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

请注意对所有读取器使用 dispatch_sync,对所有写入器使用 dispatch_barrier_async。这就是通过允许并行读取器和独占写入器来将开销降至最低的方法。如果没有争用(这是正常情况),dispatch_sync 的开销比锁(NSLock@synchronized 甚至pthreads 锁)。

参见 Migrating Away from Threads从 Apple 获得更多关于如何更好地处理 Cocoa 并发的建议。

关于ios - 在 iOS 中创建一个类 "thread safe",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28005734/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com