iOS开发常问点:GCD实现多读单写

比如在内存中维护一份数据,有多处地方可能会同时操作这块数据,怎么能保证数据安全?这道题目总结得到要满足以下三点:

  • 1.读写互斥
  • 2.写写互斥
  • 3.读读并发
@implementation KCPerson
- (instancetype)init
{
    if (self = [super init]) {
       _concurrentQueue = dispatch_queue_create("com.kc_person.syncQueue", DISPATCH_QUEUE_CONCURRENT);
       _dic = [NSMutableDictionary dictionary];
    }
    return self;
}
- (void)kc_setSafeObject:(id)object forKey:(NSString *)key{
    key = [key copy];
    dispatch_barrier_async(_concurrentQueue, ^{
       [_dic setObject:object key:key];
    });
}
- (id)kc_safeObjectForKey::(NSString *)key{
    __block NSString *temp;
    dispatch_sync(_concurrentQueue, ^{
        temp =[_dic objectForKey:key];
    });
    return temp;
}
@end
  • 首先我们要维系一个GCD 队列,最好不用全局队列,毕竟大家都知道全局队列遇到栅栏函数是有坑点的,这里就不分析了!

  • 因为考虑性能 死锁 堵塞的因素不考虑串行队列,用的是自定义的并发队列!
    _concurrentQueue = dispatch_queue_create("com.kc_person.syncQueue", DISPATCH_QUEUE_CONCURRENT);

  • 首先我们来看看读操作:kc_safeObjectForKey我们考虑到多线程影响是不能用异步函数的!说明:

    • 线程2 获取:name 线程3 获取 age
    • 如果因为异步并发,导致混乱 本来读的是name 结果读到了age
    • 我们允许多个任务同时进去! 但是读操作需要同步返回,所以我们选择:同步函数(读读并发)
  • 我们再来看看写操作,在写操作的时候对key进行了copy, 关于此处的解释,插入一段来自参考文献的引用:

函数调用者可以自由传递一个NSMutableStringkey,并且能够在函数返回后修改它。因此我们必须对传入的字符串使用copy操作以确保函数能够正确地工作。如果传入的字符串不是可变的(也就是正常的NSString类型),调用copy基本上是个空操作。

  • 这里我们选择dispatch_barrier_async, 为什么是栅栏函数而不是异步函数或者同步函数,下面分析:
    • 栅栏函数任务:之前所有的任务执行完毕,并且在它后面的任务开始之前,期间不会有其他的任务执行,这样比较好的促使 写操作一个接一个写 (写写互斥),不会乱!
    • 为什么不是异步函数?应该很容易分析,毕竟会产生混乱!
    • 为什么不用同步函数?如果读写都操作了,那么用同步函数,就有可能存在:我写需要等待读操作回来才能执行,显然这里是不合理!

阅读更多:

  • iOS开发常问点合集 ·

你可能感兴趣的:(iOS开发常问点:GCD实现多读单写)