美文网首页GCDiOS开发之多线程
【多线程】dispatch_barrier_sync 和disp

【多线程】dispatch_barrier_sync 和disp

作者: BeethOven | 来源:发表于2021-12-09 15:34 被阅读0次
    image.png
    共同点和区别

    共同点:分割queue中的任务任务执行

    区别: 是否影响主线程代码的执行

    • dispatch_barrier_async
     NSLog(@"start");
     dispatch_queue_t quque = dispatch_queue_create("name", DISPATCH_QUEUE_CONCURRENT);
     dispatch_async(quque, ^{
     NSLog(@"1");
     });
     dispatch_async(quque, ^{
     NSLog(@"2");
     });
     dispatch_barrier_async(quque, ^{
     NSLog(@"dispatch_barrier_sync");
     });
     dispatch_async(quque, ^{
     NSLog(@"3");
     });
     dispatch_async(quque, ^{
     NSLog(@"4");
     });
     NSLog(@"end");
    

    2021-12-09 10:42:13.613007+0800 TestOC[2093:1349166] start

    2021-12-09 10:42:13.613193+0800 TestOC[2093:1349166] end

    2021-12-09 10:42:13.613208+0800 TestOC[2093:1349326] 1

    2021-12-09 10:42:13.613223+0800 TestOC[2093:1349327] 2

    2021-12-09 10:42:13.613434+0800 TestOC[2093:1349326] dispatch_barrier_sync

    2021-12-09 10:42:13.613559+0800 TestOC[2093:1349326] 3

    2021-12-09 10:42:13.613568+0800 TestOC[2093:1349327] 4

    • dispatch_barrier_sync
    NSLog(@"start");
     dispatch_queue_t quque = dispatch_queue_create("name", DISPATCH_QUEUE_CONCURRENT);
     dispatch_async(quque, ^{
     NSLog(@"1");
     });
     dispatch_async(quque, ^{
     NSLog(@"2");
     });
     dispatch_barrier_sync(quque, ^{
     NSLog(@"dispatch_barrier_sync");
     });
     dispatch_async(quque, ^{
     NSLog(@"3");
     });
     dispatch_async(quque, ^{
     NSLog(@"4");
     });
     NSLog(@"end");
    
    
    start
    2021-12-09 10:43:14.680469+0800 TestOC[2122:1350990] 1
    2021-12-09 10:43:14.680495+0800 TestOC[2122:1350986] 2
    2021-12-09 10:43:14.680703+0800 TestOC[2122:1350823] dispatch_barrier_sync
    2021-12-09 10:43:14.680835+0800 TestOC[2122:1350823] end
    2021-12-09 10:43:14.680849+0800 TestOC[2122:1350986] 3
    2021-12-09 10:43:14.680853+0800 TestOC[2122:1350990] 4
    

    结论:dispatch_barrier_sync会阻塞主线程任务的执行

    注: 栅栏函数用用自定义的并发队列才有意义

    1. 尽量使用自定义的并发队列:
      使用全局队列起不到栅栏函数的作用
      使用全局队列时由于对全局队列造成堵塞,可能致使系统其他调用全局队列的地方也堵塞从而导致崩溃(并不是只有你在使用这个队列)
    1. 栅栏函数只能控制同一并发队列:打个比方,平时在使用AFNetworking做网络请求时为什么不能用栅栏函数起到同步锁堵塞的效果,因为AFNetworking内部有自己的队列
    实现读写锁(多读单写)
    
    @interface ViewController ()
    
    @property (nonatomic, strong) dispatch_queue_t rwqueue;
    
    @property (nonatomic, assign) NSInteger tickets;
    
    @end
    
    @implementation ViewController
    
     //初始化 异步队列
     self.rwqueue = dispatch_queue_create("rw.thread", DISPATCH_QUEUE_CONCURRENT);
     dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
     for (NSInteger i = 0; i < 30; i ++) {
     dispatch_async(queue, ^{
     [self readBarryier];
     [self readBarryier];
     [self writeBarrier];
     [self readBarryier];
     });
     }
    }
    
    - (void)readBarryier{
    //添加任务到rwqueue
     dispatch_async(self.rwqueue, ^{
     NSLog(@"读文件 %@ - %ld",[NSThread currentThread], self.tickets);
     sleep(1);
     });
    }
    - (void)writeBarrier{
    //barrier_async添加任务到self.rwqueue中
     dispatch_barrier_async(self.rwqueue, ^{
     self.tickets++;
     NSLog(@"写入文件 %@ - %ld",[NSThread currentThread], self.tickets);
     sleep(1);
     });
    }
    @end 
    
    - (id)readDataForKey:(NSString*)key {
     __block id result;
     dispatch_sync(_concurrentQueue, ^{
     result = [self valueForKey:key];
     });
     return result;
    }
    
    - (void)writeData:(id)data forKey:(NSString*)key {
     dispatch_barrier_async(_concurrentQueue, ^{
     [self setValue:data forKey:key];
     });
    }
    
    • 读:并发异步
      获取到值后返回给读者
      • 若使用并发异步则会先返回空的result 0x0,再通过getter方法获取到值
    • 写:写的那个时间段,不能有任何读者+其他写者
      • dispatch_barrier_async满足:等队列中前面的读写任务都执行完了再来执行当前任务

    参考文章

    相关文章

      网友评论

        本文标题:【多线程】dispatch_barrier_sync 和disp

        本文链接:https://www.haomeiwen.com/subject/uppffrtx.html