GCD实现单一资源的多读单写
解决方案与原理ARC版本 _ioQueue = dispatch_queue_create("ioQueue",DISPATCH_QUEUE_CONCURRENT); - (void)setSafeObject:(id)object forKey:(NSString *)key { key = [key copy]; dispatch_barrier_async(self.ioQueue,^{ if (key && object) { [_dic setObject:object forKey:key]; } }); } - (id)getSafeObjectForKey:(NSString *)key { __block id result = nil; dispatch_sync(self.ioQueue,^{ result = [_dic objectForKey:key]; }); return result; }
关于死锁dispatch_queue_t queueA; // 串行队列 dispatch_sync(queueA,^(){ dispatch_sync(queueA,^(){ foo(); }); }); 造成死锁比较常见的情况可以简化成上面这段代码。 值得注意的是main_queue就是一个串行队列。 MRC下容易遇到的问题与解决方案- (void)setSafeObject:(id)object forKey:(NSString *)key { key = [key copy]; dispatch_barrier_async(self.ioQueue,^{ if (key && object) { [_dic setObject:object forKey:key]; } }); [key release]; } - (id)getSafeObjectForKey:(NSString *)key { __block id result = nil; dispatch_sync(self.ioQueue,^{ result = [_dic objectForKey:key]; }); return result; } 首先我们看看上面这段代码,基本就是ARC版本转换过来的,看起来没问题。那么究竟是不是真的没问题,我们跑段代码试试看: //版本一 - (void)test { for (int i = 0; i < 1000000; i++) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{ [self setSafeObject:[NSString stringWithFormat:@"86+131633829%i",i] forKey:KEY]; }); NSString *result = [self getSafeObjectForKey:KEY]; NSLog(@"get string: %@,length : %lu",result,result.length); } } test执行后,很快就会发生crash,读操作的result会发生野指针。 这时候,你可能会采取这样子的修改,代码如下: //版本二 - (void)test { for (int i = 0; i < 1000000; i++) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,i] forKey:KEY]; }); NSString *result = [[self getSafeObjectForKey:KEY] retain]; NSLog(@"get string: %@,result.length); [result release]; } } 运行之后会发现,仍然会crash,其实问题和上面一样,我们的改动没有真正的解决问题。最好的解决方案是在读操作之前就已经 //最终版 - (id)getSafeObjectForKey:(NSString *)key { __block id result = nil; dispatch_sync(self.ioQueue,^{ result = [[_dic objectForKey:key] retain]; }); return [result autorelease]; } 注意retain过一定要释放掉,不然或造成内存泄露。 再次验证后发现,程序不会crash了。 转载请注明出处哦,我的博客: luoyibu GCD是一套很好用的多线程库,更多的用法请看参考资料 参考资料
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |