考察点:
- 并发队列 + 异步栅栏dispatch_barrier_async()
- 线程安全
- 关于资源竞争的处理
- 基于线程安全的多读单写的处理,读的操作需要立马返回结果的,所以,在读数据操作,使用同步提交任务到并发队列中
例子1:字典安全处理
在多线程编程中,最常见的场景是如何保证线程安全,比如你可能经常遇到多线程访问某个dic(又或者是array或其他)造成的crash。如何使用GCD实现多线程读者与写者问题,也即单一资源的线程安全问题。
_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;
}
例子2、多读单写解决思
读取处理是可以并发的,但是写入处理却是不允许并发执行的。
- (void)dispatch_barrier_test{
dispatch_queue_t meetingQueue = dispatch_queue_create("com.meeting.queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(meetingQueue, ^{NSLog(@"读取操作1"); });
dispatch_async(meetingQueue, ^{NSLog(@"读取操作2"); });
dispatch_async(meetingQueue, ^{NSLog(@"读取操作3"); });
dispatch_async(meetingQueue, ^{NSLog(@"读取操作4"); });
dispatch_barrier_async(meetingQueue, ^{NSLog(@"写入操作"); });
dispatch_async(meetingQueue, ^{NSLog(@"读取操作"); });
dispatch_async(meetingQueue, ^{NSLog(@"读取操作"); });
dispatch_async(meetingQueue, ^{NSLog(@"读取操作"); });
dispatch_async(meetingQueue, ^{NSLog(@"读取操作"); });
}