美文网首页
Thread Safe Mutable Objects

Thread Safe Mutable Objects

作者: 公爵海恩庭斯 | 来源:发表于2018-02-05 13:52 被阅读24次

想法来自于项目中关于 Mutable Model 操作中的各种 Crash。跟同事交流后,最终我们的分歧落在了使用何种队列来解决问题上。

方案 1 采用了串行队列,多线程读时会互相等待;方案 2 采用了并发队列,有死锁的潜在风险,以下是苹果关于 dispatch_queue_create 的一段注释

  • Dispatch queues created with the DISPATCH_QUEUE_CONCURRENT attribute may

  • invoke blocks concurrently (similarly to the global concurrent queues, but

  • potentially with more overhead), and support barrier blocks submitted with

  • the dispatch barrier API, which e.g. enables the implementation of efficient

  • reader-writer schemes.

方案 1:

NS_ASSUME_NONNULL_BEGIN

@interface WBMutableArraySerialQueue ()
{
    dispatch_queue_t _queue;
    NSMutableArray *_array;
}

@end


@implementation WBMutableArraySerialQueue

- (instancetype)initWithArray:(NSArray *)array
{
    self = [super init];
    if (self)
    {
        _queue = dispatch_queue_create([[NSString stringWithFormat:@"WBMutableArrayQueue.%@", self] UTF8String], DISPATCH_QUEUE_SERIAL);
        _array = [NSMutableArray arrayWithArray:array];
    }
    return self;
}

- (instancetype)init
{
    self = [self initWithArray:@[]];
    if (self)
    {
        
    }
    return self;
}

- (void)inQueue:(__attribute__((noescape)) void (^)(NSMutableArray *array))block
{
    dispatch_sync(_queue, ^() {
        
        block(self->_array);
    });
}

@end

NS_ASSUME_NONNULL_END

方案 2:

NS_ASSUME_NONNULL_BEGIN

@interface WBMutableArrayConcurrentQueue ()
{
    dispatch_queue_t _queue;
    NSMutableArray *_array;
}

@end


@implementation WBMutableArrayConcurrentQueue

- (instancetype)initWithArray:(NSArray *)array
{
    self = [super init];
    if (self)
    {
        _queue = dispatch_queue_create([[NSString stringWithFormat:@"WBMutableArrayQueue.%@", self] UTF8String], DISPATCH_QUEUE_CONCURRENT);
        _array = [NSMutableArray arrayWithArray:array];
    }
    return self;
}

- (instancetype)init
{
    self = [self initWithArray:@[]];
    if (self)
    {
        
    }
    return self;
}

- (void)inImmutableQueue:(__attribute__((noescape)) void (^)(NSArray *array))block
{
    dispatch_sync(_queue, ^{
        
        block((NSArray *)self->_array);
    });
    
}

- (void)inOperationQueue:(__attribute__((noescape)) void (^)(NSMutableArray *array))block
{
    dispatch_barrier_async(_queue, ^{
        
        block(self->_array);
    });
}

@end

NS_ASSUME_NONNULL_END

笔者目前的考虑是,既然选择了多线程读,那么在子线程中,对于“等待”的不耐就是低的。方案 1 串行队列开销小,没有死锁风险,是目前最优的折衷方案。

如果你有不同的意见,欢迎留言。

另外,YYThreadSafeArray 使用了锁包装了所有 MutableArray 的方法,这是一个崭新的思路。名义上是继承 NSMutableArray,实际上内部是组合了一个 NSMutableArray。一个可能的原因是他可能懒得在声明一遍那些本应该属于 NSMutableArray 的方法。
YYThreadSafeArray 的插入效率测试不如 Queue,但是拜父类继承所致,实际解决 bug 时,因为方法完全一致,排查 Crash 替换成本较低。


WBMutableArrayQueue vs YYThreadSafeArray

相关文章

网友评论

      本文标题:Thread Safe Mutable Objects

      本文链接:https://www.haomeiwen.com/subject/kknbzxtx.html