dispatch_barrier_sync 和dispatch_barrier_async的区别

需求:有4个任务{1,2,3,4},执行完前2个再执行后2个

这里我们用到栅栏函数dispatch_barrier_(a)sync,(也可以用队列组),我们要注意的是不能使用全局并发队列(系统提供给我们的)否则会散失栅栏函数的意义

区别:先看官方文档

dispatch_barrier_sync: Submits a barrier block object for execution and waits until that block completes.(提交一个栅栏函数在执行中,它会等待栅栏函数执行完)

dispatch_barrier_async: Submits a barrier block for asynchronous execution and returns immediately.(提交一个栅栏函数在异步执行中,它会立马返回)

第一种解释

作者理解:dispatch_barrier_sync 需要等待栅栏执行完才会执行栅栏后面的任务,
而dispatch_barrier_async 无需等待栅栏执行完,会继续往下走(保留在队列里)

原因:在同步栅栏时栅栏函数在主线程中执行,而异步栅栏中开辟了子线程栅栏函数在子线程中执行

1.先来看看dispatch_barrier_sync

- (void) barrier {
    NSLog(@"start");
    
    dispatch_queue_t myQueue = dispatch_queue_create("ff", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(myQueue, ^{
        NSLog(@"%@--1", [NSThread currentThread]);
    });
    dispatch_async(myQueue, ^{
           NSLog(@"%@--2", [NSThread currentThread]);
       });
    
    dispatch_barrier_sync(myQueue, ^{
        NSLog(@"+++barrier ++++++");
    });
    NSLog(@"++++++++++++barrier 之后");
    
    dispatch_async(myQueue, ^{
          NSLog(@"%@--3", [NSThread currentThread]);
      });
      dispatch_async(myQueue, ^{
             NSLog(@"%@--4", [NSThread currentThread]);
         });
    NSLog(@"last");
}

打印结果:

2020-06-20 08:31:08.892663+0800 OCTestFirst[6439:172483] start
2020-06-20 08:31:08.893001+0800 OCTestFirst[6439:172646] <NSThread: 0x600002a48440>{number = 6, name = (null)}--2
2020-06-20 08:31:08.893007+0800 OCTestFirst[6439:172648] <NSThread: 0x600002a4aa40>{number = 5, name = (null)}--1
2020-06-20 08:31:08.893166+0800 OCTestFirst[6439:172483] +++barrier ++++++
2020-06-20 08:31:08.893274+0800 OCTestFirst[6439:172483] ++++++++++++barrier 之后
2020-06-20 08:31:08.893375+0800 OCTestFirst[6439:172483] last
2020-06-20 08:31:08.893430+0800 OCTestFirst[6439:172646] <NSThread: 0x600002a48440>{number = 6, name = (null)}--4
2020-06-20 08:31:08.893488+0800 OCTestFirst[6439:172648] <NSThread: 0x600002a4aa40>{number = 5, name = (null)}--3

得到结果:栅栏函数确实分割了任务,但是任务执行的顺序的确是无序的(异步函数)

2 换成dispatch_barrier_async

- (void) barrier {
    NSLog(@"start");
    
    dispatch_queue_t myQueue = dispatch_queue_create("ff", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(myQueue, ^{
        NSLog(@"%@--1", [NSThread currentThread]);
    });
    dispatch_async(myQueue, ^{
           NSLog(@"%@--2", [NSThread currentThread]);
       });
    
    dispatch_barrier_async(myQueue, ^{
        NSLog(@"+++barrier ++++++");
    });
    NSLog(@"++++++++++++barrier 之后");
    
    dispatch_async(myQueue, ^{
          NSLog(@"%@--3", [NSThread currentThread]);
      });
      dispatch_async(myQueue, ^{
             NSLog(@"%@--4", [NSThread currentThread]);
         });
    NSLog(@"last");
}

打印结果

2020-06-20 08:34:09.223552+0800 OCTestFirst[6485:174586] start
2020-06-20 08:34:09.223936+0800 OCTestFirst[6485:174586] ++++++++++++barrier 之后
2020-06-20 08:34:09.224071+0800 OCTestFirst[6485:174586] last
2020-06-20 08:34:09.225737+0800 OCTestFirst[6485:175133] <NSThread: 0x60000371bb00>{number = 10, name = (null)}--2
2020-06-20 08:34:09.225876+0800 OCTestFirst[6485:174911] <NSThread: 0x600003702440>{number = 8, name = (null)}--1
2020-06-20 08:34:09.226888+0800 OCTestFirst[6485:175133] +++barrier ++++++
2020-06-20 08:34:09.227540+0800 OCTestFirst[6485:175133] <NSThread: 0x60000371bb00>{number = 10, name = (null)}--3
2020-06-20 08:34:09.227540+0800 OCTestFirst[6485:174911] <NSThread: 0x600003702440>{number = 8, name = (null)}--4

特别注意:

The queue you specify should be a concurrent queue that you create yourself using the dispatch_queue_create function. If the queue you pass to this function is a serial queue or one of the global concurrent queues, this function behaves like the dispatch_sync function.

官方说明大意:在使用栅栏函数时.使用自定义队列才有意义,如果用的是串行队列或者系统提供的全局并发队列,这个栅栏函数的作用等同于一个同步函数的作用

第二种解释

在这里插入图片描述
barrier里给了一个比较费时的操作便于看清楚

给的图里写的是dispatch_barrier_sync,因为我们需要先看看我们熟悉的等待——sync是什么效果,直接跑起来
在这里插入图片描述
可以看到,确实是1、2、3号任务并发执行完了,然后再执行的我们的0号任务,再并发执行的4、5、6号任务,当然,point3和barrier之间是有明显停顿的,截图无法表现。对于这个输出,应该是意料之中的。

接下来,代码进行一点点修改,dispatch_barrier_sync改成dispatch_barrier_async。
在这里插入图片描述
区别很明显,跟sync的情况相比,aaa、bbb的输出位置完全不同,async的时候aaa的输出在任务0结束之前,sync的aaa输出在任务0结束之后

好了,说到这应该差不多能想通了,我们开始总结
dispatch_barrier_sync和dispatch_barrier_async的共同点:
1、都会等待在它前面插入队列的任务(1、2、3)先执行完
2、都会等待他们自己的任务(0)执行完再执行后面的任务(4、5、6)
dispatch_barrier_sync和dispatch_barrier_async的不共同点:
在将任务插入到queue的时候,dispatch_barrier_sync需要等待自己的任务(0)结束之后才会继续程序,然后插入被写在它后面的任务(4、5、6),然后执行后面的任务
而dispatch_barrier_async将自己的任务(0)插入到queue之后,不会等待自己的任务结束,它会继续把后面的任务(4、5、6)插入到queue

原文链接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章