美文网首页
iOS NSMutableArray,NSMutableDict

iOS NSMutableArray,NSMutableDict

作者: justjustjust | 来源:发表于2023-11-12 14:55 被阅读0次

    对于一个NSString这样的属性,我们可以通过修改其原子性atomic,来保证其线程安全。但是对于NSMutableArray和NSMutableDictionary这样的对象,却无法通过这样的方案保障其线程安全。

    通常为了保证可变容器的线程安全,我们会采用加读写锁或者采用GCD队列的方式保障其线程安全。加读写锁,可以保障线程安全,但是会失去多线程的优势。所以这里我们着重介绍一下通过GCD队列实现可变容器线程安全的方案。

    首先介绍一下 dispatch_barrier_async

    /*!
     * @function dispatch_barrier_async
     *
     * @abstract
     * Submits a barrier block for asynchronous execution on a dispatch queue.
     *
     * @discussion
     * Submits a block to a dispatch queue like dispatch_async(), but marks that
     * block as a barrier (relevant only on DISPATCH_QUEUE_CONCURRENT queues).
     *
     * See dispatch_async() for details and "Dispatch Barrier API" for a description
     * of the barrier semantics.
     *
     * @param queue
     * The target dispatch queue to which the block is submitted.
     * The system will hold a reference on the target queue until the block
     * has finished.
     * The result of passing NULL in this parameter is undefined.
     *
     * @param block
     * The block to submit to the target dispatch queue. This function performs
     * Block_copy() and Block_release() on behalf of callers.
     * The result of passing NULL in this parameter is undefined.
     */
    #ifdef __BLOCKS__
    API_AVAILABLE(macos(10.7), ios(4.3))
    DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
    DISPATCH_REFINED_FOR_SWIFT
    void
    dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);
    #endif
    

    dispatch_barrier_async栅栏函数,可以将添加到队列中的所有任务分割开,在barrier之前添加的任务会在barrier之前执行,在barrier之后添加的任务会在barrier之后执行。因此,我们可以在执行写操作(如:addObject,removeObjectAtIndex等)时,通过dispatch_barrier_async添加任务,在执行读操作(如:objectAtIndex,indexOfObject等)时,通过dispatch_async添加任务。

    但是,通过dispatch_async添加任务来执行读操作时,dispatch_async是另外开辟线程去执行的,不是立马返回的,所以我们不能立刻拿到执行结果,需要另写一个方法来返回读的结果,这和常规调用习惯不符。因此,这里我们不再采用dispatch_async,而是采用dispatch_sync。

    dispatch_sync是在当前线程上执行,不会另外开辟新的线程,当线程返回的时候就可以拿到读取的结果。

    下面拿NSMutableArray为例,讲一下具体实现:

    这里要注意一点,dispatch_barrier_async仅对自定义并发队列DISPATCH_QUEUE_CONCURRENT有效。如果传递给此函数的队列是串行队列或全局并发队列之一,则此函数的行为类似于dispatch_sync函数。

    - (instancetype)init {
        if (self = [super init]) {
            self.mArray = [[NSMutableArray alloc] initWithCapacity:0];
            self.safeQueue = dispatch_queue_create("safe.mutableArray.queue", DISPATCH_QUEUE_CONCURRENT);
        }
        return self;
    }
    
    - (void)addObject:(id)object {
        
        dispatch_barrier_async(self.safeQueue, ^{
            [self.mArray addObject:object];
        });
    }
    
    - (id)objectAtIndex:(NSUInteger)index; {
        
        __block id result = nil;
        
        dispatch_sync(self.safeQueue, ^{
            result = [self.mArray objectAtIndex:index];
        });
        
        return result;
    }
    

    相关文章

      网友评论

          本文标题:iOS NSMutableArray,NSMutableDict

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