美文网首页
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