美文网首页selector
详解GCD<2>-dispatch_barrier

详解GCD<2>-dispatch_barrier

作者: FreeBreath | 来源:发表于2018-02-09 17:28 被阅读13次

    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任务,又有什么意义呢?

    相关文章

      网友评论

        本文标题:详解GCD<2>-dispatch_barrier

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