详解GCD<2>-dispatch_barrier

dispatch_barrier

讲完了GCD详解一。我们来看看一个不太常用的GCD。dispatch_barrier。 这个barrier我感觉使用霸道总裁形容比较合适。这里借用raywenderlich上介绍barrier的一张图。


看的有点懵逼?

不要紧。我来解释一下。 首先,在一个并行队列中,有多个线程在执行多个任务,在这个并行队列中,有一个dispatch_barrier任务。这样会有一个什么效果呢? 就是,所有在这个dispatch_barrier之后的任务总会等待barrier之前的所有任务结束之后,才会执行。那么细心的同学可能会发现这里有个问题,既然所有在barrier之后的任务都会等待在barrier之前的任务结束之后执行,那么barrier本身执行是否会阻塞当前线程? 所以,dispatch_barrier也是有两个方法的。dispatch_barrier_sync和dispatch_barrier_async.

dispatch_barrier_sync

还是看代码理解的更快一点。代码如下:

-(void)testBarrierSyncWithConcurrentQueue

{

    dispatch_queue_t  concurrtqueue = dispatch_queue_create("thread", DISPATCH_QUEUE_CONCURRENT);

    for (int index=0; index<10; index++) {

        dispatch_async(concurrtqueue, ^{

            NSLog(@"index = --%d",index);

        });

    }

    for (int j=0; j<50000; j++) {

        dispatch_barrier_sync(concurrtqueue, ^{

            if (j == 50000-1) {

                NSLog(@"barrier finished");

                NSLog(@"currt thread is %@",[NSThread currentThread]);

            }

        });

    }

    NSLog(@"Running on thread");

    for (int index = 10; index<20; index++) {

        dispatch_async(concurrtqueue, ^{

            NSLog(@"index = %d",index);

        });

    }

}

运行之后的输出结果是:

2018-01-31 16:56:17.519821+0800 TextD[24970:708808] index = --0 

2018-01-31 16:56:17.519821+0800 TextD[24970:708810] index = --1 2018-01-31 16:56:17.519822+0800 TextD[24970:708809] index = --2 

2018-01-31 16:56:17.519835+0800 TextD[24970:708807] index = --3 

2018-01-31 16:56:17.520029+0800 TextD[24970:708808] index = --4 

2018-01-31 16:56:17.520037+0800 TextD[24970:708809] index = --5 

2018-01-31 16:56:17.520040+0800 TextD[24970:708807] index = --6 

2018-01-31 16:56:17.520047+0800 TextD[24970:708810] index = --7 

2018-01-31 16:56:17.520113+0800 TextD[24970:708911] index = --8 

2018-01-31 16:56:17.520125+0800 TextD[24970:708910] index = --9 

2018-01-31 16:56:17.525035+0800 TextD[24970:708717] barrier finished 

2018-01-31 16:56:17.525376+0800 TextD[24970:708717] currt thread is<NSThread: 0x604000070f00>{number = 1, name = main}

2018-01-31 16:56:17.525520+0800 TextD[24970:708717] Running on thread

2018-01-31 16:56:17.525684+0800 TextD[24970:708910] index = 10

2018-01-31 16:56:17.525694+0800 TextD[24970:708911] index = 11

2018-01-31 16:56:17.525712+0800 TextD[24970:708810] index = 12

2018-01-31 16:56:17.525732+0800 TextD[24970:708807] index = 13

2018-01-31 16:56:17.525740+0800 TextD[24970:708809] index = 14

2018-01-31 16:56:17.525769+0800 TextD[24970:708808] index = 15

2018-01-31 16:56:17.525825+0800 TextD[24970:708912] index = 16

2018-01-31 16:56:17.525870+0800 TextD[24970:708910] index = 18

2018-01-31 16:56:17.525878+0800 TextD[24970:708913] index = 17

2018-01-31 16:56:17.525914+0800 TextD[24970:708914] index = 19

ok,总结一下。

dispatch_barrier_sync确实是会在队列中充当一个栅栏的作用,凡是在他之后进入队列的任务,总会在dispatch_barrier_sync之前的所有任务执行完毕之后才执行。

见名知意,dispatch_barrier_sync是会在主线程执行队列中的任务的,所以,Running on Main Thread这句话会被阻塞,从而在barrier之后执行。

dispatch_barrier_async

再看看dispatch_barrier_async执行的效果。

代码如下:

-(void)testBarrierAsyncWithConcurrentQueue

{

    dispatch_queue_t  concurrtqueue = dispatch_queue_create("thread", DISPATCH_QUEUE_CONCURRENT);

    for (int index=0; index<10; index++) {

        dispatch_async(concurrtqueue, ^{

            NSLog(@"index = --%d",index);

        });

    }

    for (int j=0; j<1000000; j++) {

        dispatch_barrier_async(concurrtqueue, ^{

            if (j == 1000000-1) {

                NSLog(@"barrier finished");

                NSLog(@"currt thread is %@",[NSThread currentThread]);

            }

        });

    }

    NSLog(@"Running on thread");

    for (int index = 10; index<20; index++) {

        dispatch_async(concurrtqueue, ^{

            NSLog(@"index = %d",index);

        }); 

 }

}

结果如下:

2018-02-01 15:21:45.486359+0800 TextD[3219:197349] index = --2

2018-02-01 15:21:45.486359+0800 TextD[3219:197351] index = --1

2018-02-01 15:21:45.486359+0800 TextD[3219:197352] index = --02018-02-01 15:21:45.486386+0800 TextD[3219:197348] index = --3

2018-02-01 15:21:45.486650+0800 TextD[3219:197351] index = --5

2018-02-01 15:21:45.486649+0800 TextD[3219:197352] index = --4

2018-02-01 15:21:45.486687+0800 TextD[3219:197350] index = --6

2018-02-01 15:21:45.486688+0800 TextD[3219:197349] index = --7

2018-02-01 15:21:45.486736+0800 TextD[3219:197359] index = --8

2018-02-01 15:21:45.486753+0800 TextD[3219:197360] index = --9

2018-02-01 15:21:48.984586+0800 TextD[3219:197244] Running on thread

2018-02-01 15:21:48.997644+0800 TextD[3219:197360] barrier finished

2018-02-01 15:21:48.997871+0800 TextD[3219:197360] currt thread is<NSThread: 0x6040004706c0>{number = 3, name = (null)}

2018-02-01 15:21:48.998662+0800 TextD[3219:197360] index = 11

2018-02-01 15:21:48.998662+0800 TextD[3219:197350] index = 10

2018-02-01 15:21:48.998693+0800 TextD[3219:197349] index = 12

2018-02-01 15:21:48.998714+0800 TextD[3219:197352] index = 13

2018-02-01 15:21:48.998733+0800 TextD[3219:197351] index = 14

2018-02-01 15:21:48.998750+0800 TextD[3219:197348] index = 15

2018-02-01 15:21:48.998786+0800 TextD[3219:197359] index = 16

2018-02-01 15:21:48.998866+0800 TextD[3219:197401] index = 17

2018-02-01 15:21:48.998891+0800 TextD[3219:197402] index = 18

2018-02-01 15:21:48.998916+0800 TextD[3219:197403] index = 19

dispatch_barrier_async会开辟一条新的线程执行其中的任务,所以不会阻塞当前线程。其他的功能和dispatch_barrier_sync相同。

几个小问题

1.为什么我们只举了barrier和并行队列的例子,而没有举barrier和串行队列的例子?

因为,barrier和串行队列配合是完全没有意义的。barrier的目的是什么?目的是为了在某种情况下,同一个队列中一些并发任务必须在另一些并发任务之后执行,所以需要一个类似于拦截的功能,迫使后执”

“行的任务必须等待。那么,串行队列中的所有任务本身就是按照顺序执行的,那么又有什么必要使用拦截的功能呢?

2.在global queue中使用barrier没有意义,为什么?

barrier实现的基本条件是,要写在同一队列中。举个例子,你现在创建了两个并行队列,你在其中一个队列中插入了一个barrier任务,那么你不可能期待他可以在第二个队列中生效,对吧。同样的,每一次使用global queue,系统分配给你的可能是不同的并行队列,你在其中插入一个barrier任务,又有什么意义呢?

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 曾经有一份美好的爱情放在我的面前我没有珍惜。等到失去后才后悔莫及。如果可以再对小李说。毛欣想说。这辈子无缘再牵手。...
    毛欣与小李阅读 2,721评论 0 13
  • GCD有三种queue main queue: 主线程队列。是一个串行队列。一般用来更新UI。 global qu...
    FreeBreath阅读 650评论 0 0
  • 这大概是我心里永远好不了的伤疤吧,我很爱很爱他,每次抱着别人家软软糯糯的孩子我都觉得那一刻真的特别美好,每次提起孩...
    艽小野阅读 316评论 0 0
  • 在一个夏日的正午 太阳炙烤着金灿灿的马路 像是翠嫩的枝条必须顶着烈日生长 我在这条路上晃荡 像是第一次接触夏日的季...
    止文阅读 498评论 0 6