考察点:

  • 并发队列 + 异步栅栏dispatch_barrier_async()
  • 线程安全
  • 关于资源竞争的处理
  • 基于线程安全的多读单写的处理,读的操作需要立马返回结果的,所以,在读数据操作,使用同步提交任务到并发队列中

截屏2020-12-27 上午10.51.49.png

截屏2020-12-27 上午11.06.18.png

例子1:字典安全处理

在多线程编程中,最常见的场景是如何保证线程安全,比如你可能经常遇到多线程访问某个dic(又或者是array或其他)造成的crash。如何使用GCD实现多线程读者与写者问题,也即单一资源的线程安全问题。

  1. _ioQueue = dispatch_queue_create("ioQueue", DISPATCH_QUEUE_CONCURRENT);
  2. - (void)setSafeObject:(id)object forKey:(NSString *)key {
  3. key = [key copy];
  4. dispatch_barrier_async(self.ioQueue, ^{
  5. if (key && object) {
  6. [_dic setObject:object forKey:key];
  7. }
  8. });
  9. }
  10. - (id)getSafeObjectForKey:(NSString *)key {
  11. __block id result = nil;
  12. dispatch_sync(self.ioQueue, ^{
  13. result = [_dic objectForKey:key];
  14. });
  15. return result;
  16. }

例子2、多读单写解决思

读取处理是可以并发的,但是写入处理却是不允许并发执行的。

  1. - (void)dispatch_barrier_test{
  2. dispatch_queue_t meetingQueue = dispatch_queue_create("com.meeting.queue", DISPATCH_QUEUE_CONCURRENT);
  3. dispatch_async(meetingQueue, ^{NSLog(@"读取操作1"); });
  4. dispatch_async(meetingQueue, ^{NSLog(@"读取操作2"); });
  5. dispatch_async(meetingQueue, ^{NSLog(@"读取操作3"); });
  6. dispatch_async(meetingQueue, ^{NSLog(@"读取操作4"); });
  7. dispatch_barrier_async(meetingQueue, ^{NSLog(@"写入操作"); });
  8. dispatch_async(meetingQueue, ^{NSLog(@"读取操作"); });
  9. dispatch_async(meetingQueue, ^{NSLog(@"读取操作"); });
  10. dispatch_async(meetingQueue, ^{NSLog(@"读取操作"); });
  11. dispatch_async(meetingQueue, ^{NSLog(@"读取操作"); });
  12. }