iOS 从多读单写的实现来谈,可变数组的线程安全.

3882

最近突然想回顾一下,可变数组的线程安全问题,也就随手翻了一下之前看过的YYKit的实现,是通过信号量来控制实现.但是信号量值为1,这样是线程的安全的但是限制了多读的条件.于是又翻了网上最近实现的一些方法,来更新自己之前的认知.

目前网上大部分的实现方法都是通过,dispatch_barrier_async 来实现单写. 通过并行+同步 来实现多读.

下面我们来具体来走一遍: 首先创建一个可变数组的对象:(当然也可以通过分类来实现)

  • 创建一个并行线程用来分配度操作.
#import "SafeMutableArr.h"
@interface  SafeMutableArr ()
/**
 *
 */
@property (nonatomic, strong) dispatch_queue_t ayncQueue;
/**
 *
 */
@property (nonatomic, strong) NSMutableArray  *array;
@end
@implementation SafeMutableArr
- (instancetype)initCommon
{
    self = [super init];
    if (self) {
        NSString *uuid = [NSString stringWithFormat:@"com.shuxia.array_%p",self];
        
        _ayncQueue = dispatch_queue_create([uuid UTF8String], DISPATCH_QUEUE_CONCURRENT);
    }
    return self;
}
- (instancetype)init
{
    self = [self initCommon];
    if (self) {
        _array = [NSMutableArray array];
    }
    return self;
}
#pragma mark ---数组 
-(NSMutableArray *)safeArray{

    __block NSMutableArray *safeArra;
    dispatch_sync(_ayncQueue, ^{
        safeArra = _array;
    });
    return safeArra;
}

凡是涉及到对数组元素进行修改的,都是用栅栏函数进行限制同步执行. 凡是涉及读取操作都是用同步+并行来进行派发.简单举两个例子

  • 对数组进行插入元素:
- (void)insertObject:(id)anObject atIndext:(NSUInteger) index{

    dispatch_barrier_async(_ayncQueue, ^{
        if (anObject && index < [self->_array count]) {
            [self->_array insertObject:anObject atIndex:index];
        }
    });
}
  • 查询当前数组的个数
#pragma mark ---是否包含某个元素
- (BOOL)containObject:(id)anObject{
    __block BOOL isExist;
    dispatch_sync(_ayncQueue, ^{
        isExist = [_array containsObject:anObject];
    });
    return isExist;
}