dispatch_barrier_(a)sync

barrier是栅栏的意思,gcd的栅栏函数的作用:即阻挡

异步和同步的栅栏函数都有以下特点:

1、通过dispatch_barrier_(a)sync添加的block会等待前边所有的block执行完(不包括回调)才执行。

2、在其后添加的block会在dispatch_barrier_(a)sync添加的block执行完之后(不包括回调)再执行;

不同点:

1、dispatch_barrier_sync:同步栅栏函数在原线程中执行block,不开辟新线程;在将任务插入到queue的时候,       dispatch_barrier_sync需要等待自己的任务结束之后才会继续程序,然后插入被写在它后面的任务。

2、dispatch_barrier_async:异步栅栏函数会开辟新线程执行block;ispatch_barrier_async将自己的任务插入到queue之后,不会等待自己的任务结束,它会继续把后面的任务插入到queue。

看下以下几个例子:

例1:示例代码testSyncBarrier方法:同步栅栏函数 + 无等待回调

{//同步栅栏函数

扫描二维码关注公众号,回复: 3796244 查看本文章

    //并行队列

    dispatch_queue_t asynQueue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);

    dispatch_async(asynQueue, ^{

        NSLog(@"无等待的回调任务1:%@",[NSThread currentThread]);

    });

    dispatch_async(asynQueue, ^{

        NSLog(@"无等待的回调任务2:%@",[NSThread currentThread]);

    });

    NSLog(@"我在同步栅栏函数之前:%@",[NSThread currentThread]);

    //同步栅栏函数

    dispatch_barrier_sync(asynQueue, ^{

        NSLog(@"我是无等待回调的同步栅栏函数block块:%@",[NSThread currentThread]);

    });

    NSLog(@"我在同步栅栏函数之后:%@",[NSThread currentThread]);

    dispatch_async(asynQueue, ^{

        NSLog(@"无等待的回调任务3:%@",[NSThread currentThread]);

    });

    dispatch_async(asynQueue, ^{

        NSLog(@"无等待的回调任务4:%@",[NSThread currentThread]);

    });

//        {//打印

//            2018-10-24 20:24:50.158128+0800 dispatch_barrier_sync[18990:2037305] 无等待的回调任务1:<NSThread: 0x600003512800>{number = 3, name = (null)}

//            2018-10-24 20:24:50.158159+0800 dispatch_barrier_sync[18990:2037240] 我在同步栅栏函数之前:<NSThread: 0x60000354e540>{number = 1, name = main}

//            2018-10-24 20:24:50.158207+0800 dispatch_barrier_sync[18990:2037303] 无等待的回调任务2:<NSThread: 0x60000352d240>{number = 4, name = (null)}

//            2018-10-24 20:24:50.158414+0800 dispatch_barrier_sync[18990:2037240] 我是无等待回调的同步栅栏函数block块:<NSThread: 0x60000354e540>{number = 1, name = main}

//            2018-10-24 20:24:50.158544+0800 dispatch_barrier_sync[18990:2037240] 我在同步栅栏函数之后:<NSThread: 0x60000354e540>{number = 1, name = main}

//            2018-10-24 20:24:50.158704+0800 dispatch_barrier_sync[18990:2037303] 无等待的回调任务3:<NSThread: 0x60000352d240>{number = 4, name = (null)}

//            2018-10-24 20:24:50.158710+0800 dispatch_barrier_sync[18990:2037305] 无等待的回调任务4:<NSThread: 0x600003512800>{number = 3, name = (null)}

//        }

    //同步栅栏函数,前边的打印、栅栏函数block内的任务、后边的打印都在主线程 同步

}

例2、示例代码testAsyncBarrier方法:异步步栅栏函数 + 无等待回调

{//异步栅栏函数

    //并行队列

    dispatch_queue_t asynQueue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);

    dispatch_async(asynQueue, ^{

        NSLog(@"无等待的回调任务1:%@",[NSThread currentThread]);

    });

    dispatch_async(asynQueue, ^{

        NSLog(@"无等待的回调任务2:%@",[NSThread currentThread]);

    });

    NSLog(@"我在异步步栅栏函数之前:%@",[NSThread currentThread]);

    //异步栅栏函数

    dispatch_barrier_async(asynQueue, ^{

        NSLog(@"我是无等待回调的异步栅栏函数block块:%@",[NSThread currentThread]);

    });

    NSLog(@"我在异步栅栏函数之后:%@",[NSThread currentThread]);

    dispatch_async(asynQueue, ^{

        NSLog(@"无等待的回调任务3:%@",[NSThread currentThread]);

    });

    dispatch_async(asynQueue, ^{

        NSLog(@"无等待的回调任务4:%@",[NSThread currentThread]);

    });

    

//    {//打印

//        2018-10-24 20:28:00.626533+0800 dispatch_barrier_sync[19060:2042379] 我在异步步栅栏函数之前:<NSThread: 0x600000c113c0>{number = 1, name = main}

//        2018-10-24 20:28:00.626540+0800 dispatch_barrier_sync[19060:2042429] 无等待的回调任务2:<NSThread: 0x600000c75780>{number = 4, name = (null)}

//        2018-10-24 20:28:00.626585+0800 dispatch_barrier_sync[19060:2042431] 无等待的回调任务1:<NSThread: 0x600000c756c0>{number = 3, name = (null)}

//        2018-10-24 20:28:00.626770+0800 dispatch_barrier_sync[19060:2042379] 我在异步栅栏函数之后:<NSThread: 0x600000c113c0>{number = 1, name = main}

//        2018-10-24 20:28:00.626777+0800 dispatch_barrier_sync[19060:2042429] 我是无等待回调的异步栅栏函数block块:<NSThread: 0x600000c75780>{number = 4, name = (null)}

//        2018-10-24 20:28:00.626938+0800 dispatch_barrier_sync[19060:2042429] 无等待的回调任务3:<NSThread: 0x600000c75780>{number = 4, name = (null)}

//        2018-10-24 20:28:00.626949+0800 dispatch_barrier_sync[19060:2042431] 无等待的回调任务4:<NSThread: 0x600000c756c0>{number = 3, name = (null)}

//

//    }

    //异步栅栏函数,前边的打印和后边的打印都在主线程,而异步栅栏函数内的任务在子线程 异步

}

由上边两个例子可知;dispatch_barrier_async的不等待(异步)特性体现在将任务插入队列的过程,它的等待特性体现在任务真正执行的过程。

以上例1例2所有任务都不包含回调,为了进一步理解栅栏函数执行效果,把上边两个例子的任务换成耗时的图片下载任务

例3:示例代码testSyncBarrierRequest  同步栅栏函数+有回调的接口

{//同步栅栏函数+有回调的接口

        //并行队列

        dispatch_queue_t asynQueue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);

        dispatch_async(asynQueue, ^{

            NSLog(@"耗时回调任务1:%@",[NSThread currentThread]);

            NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:@"https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/static/protocol/https/home/img/qrcode/zbios_efde696.png"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

                UIImage *image = [UIImage imageWithData:data];

                NSLog(@"请求1返回了");

            }];

            [task resume];

        });

        dispatch_async(asynQueue, ^{

            NSLog(@"耗时回调任务2:%@",[NSThread currentThread]);

            NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:@"https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/static/protocol/https/home/img/qrcode/zbios_efde696.png"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

                UIImage *image = [UIImage imageWithData:data];

                NSLog(@"请求2返回了");

            }];

            [task resume];

        });

        NSLog(@"我在同步栅栏函数之前:%@",[NSThread currentThread]);

        //同步栅栏函数

        dispatch_barrier_sync(asynQueue, ^{

            NSLog(@"我是耗时回调的同步栅栏函数block块:%@",[NSThread currentThread]);

            NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:@"https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/static/protocol/https/home/img/qrcode/zbios_efde696.png"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

                UIImage *image = [UIImage imageWithData:data];

                NSLog(@"请求zl返回了");

            }];

            [task resume];

        });

        NSLog(@"我在同步栅栏函数之后:%@",[NSThread currentThread]);

        dispatch_async(asynQueue, ^{

            NSLog(@"耗时回调任务3:%@",[NSThread currentThread]);

            NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:@"https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/static/protocol/https/home/img/qrcode/zbios_efde696.png"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

                UIImage *image = [UIImage imageWithData:data];

                NSLog(@"请求3返回了");

            }];

            [task resume];

        });

        dispatch_async(asynQueue, ^{

            NSLog(@"耗时回调任务4:%@",[NSThread currentThread]);

            NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:@"https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/static/protocol/https/home/img/qrcode/zbios_efde696.png"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

                UIImage *image = [UIImage imageWithData:data];

                NSLog(@"请求4返回了");

            }];

            [task resume];

        });

//                {//打印

//                    2018-10-24 20:40:45.701838+0800 dispatch_barrier_sync[19214:2061713] 我在同步栅栏函数之前:<NSThread: 0x600001be0e80>{number = 1, name = main}

//                    2018-10-24 20:40:45.701838+0800 dispatch_barrier_sync[19214:2061779] 耗时回调任务1:<NSThread: 0x600001b89080>{number = 3, name = (null)}

//                    2018-10-24 20:40:45.701838+0800 dispatch_barrier_sync[19214:2061778] 耗时回调任务2:<NSThread: 0x600001bbe900>{number = 4, name = (null)}

//                    2018-10-24 20:40:45.705053+0800 dispatch_barrier_sync[19214:2061713] 我是耗时回调的同步栅栏函数block块:<NSThread: 0x600001be0e80>{number = 1, name = main}

//                    2018-10-24 20:40:45.705623+0800 dispatch_barrier_sync[19214:2061713] 我在同步栅栏函数之后:<NSThread: 0x600001be0e80>{number = 1, name = main}

//                    2018-10-24 20:40:45.705823+0800 dispatch_barrier_sync[19214:2061778] 耗时回调任务3:<NSThread: 0x600001bbe900>{number = 4, name = (null)}

//                    2018-10-24 20:40:45.705829+0800 dispatch_barrier_sync[19214:2061779] 耗时回调任务4:<NSThread: 0x600001b89080>{number = 3, name = (null)}

//                    2018-10-24 20:40:45.799049+0800 dispatch_barrier_sync[19214:2061778] 请求1返回了

//                    2018-10-24 20:40:45.800109+0800 dispatch_barrier_sync[19214:2061776] 请求2返回了

//                    2018-10-24 20:40:45.800817+0800 dispatch_barrier_sync[19214:2061777] 请求zl返回了

//                    2018-10-24 20:40:45.801467+0800 dispatch_barrier_sync[19214:2061777] 请求3返回了

//                    2018-10-24 20:40:45.802519+0800 dispatch_barrier_sync[19214:2061777] 请求4返回了

//

//                }

        //同步栅栏函数,前边的打印、栅栏函数block内的任务、后边的打印都在主线程 同步

}

例4:示例代码testAsyncBarrierRequest   //异步栅栏函数+有回调的接口

{//异步栅栏函数+有回调的接口

        //并行队列

        dispatch_queue_t asynQueue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);

        dispatch_async(asynQueue, ^{

            NSLog(@"耗时回调任务1:%@",[NSThread currentThread]);

            NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:@"https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/static/protocol/https/home/img/qrcode/zbios_efde696.png"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

                UIImage *image = [UIImage imageWithData:data];

                NSLog(@"请求1返回了");

            }];

            [task resume];

        });

        dispatch_async(asynQueue, ^{

            NSLog(@"耗时回调任务2:%@",[NSThread currentThread]);

            NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:@"https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/static/protocol/https/home/img/qrcode/zbios_efde696.png"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

                UIImage *image = [UIImage imageWithData:data];

                NSLog(@"请求2返回了");

            }];

            [task resume];

        });

        NSLog(@"我在异步栅栏函数之前:%@",[NSThread currentThread]);

        //同步栅栏函数

        dispatch_barrier_async(asynQueue, ^{

            NSLog(@"我是耗时回调的异步栅栏函数block块:%@",[NSThread currentThread]);

            NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:@"https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/static/protocol/https/home/img/qrcode/zbios_efde696.png"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

                UIImage *image = [UIImage imageWithData:data];

                NSLog(@"请求zl返回了");

            }];

            [task resume];

        });

        NSLog(@"我在异步栅栏函数之后:%@",[NSThread currentThread]);

        dispatch_async(asynQueue, ^{

            NSLog(@"耗时回调任务3:%@",[NSThread currentThread]);

            NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:@"https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/static/protocol/https/home/img/qrcode/zbios_efde696.png"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

                UIImage *image = [UIImage imageWithData:data];

                NSLog(@"请求3返回了");

            }];

            [task resume];

        });

        dispatch_async(asynQueue, ^{

            NSLog(@"耗时回调任务4:%@",[NSThread currentThread]);

            NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:@"https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/static/protocol/https/home/img/qrcode/zbios_efde696.png"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

                UIImage *image = [UIImage imageWithData:data];

                NSLog(@"请求4返回了");

            }];

            [task resume];

        });

        

//    {//打印

//        2018-10-24 20:43:12.156237+0800 dispatch_barrier_sync[19254:2065765] 我在异步栅栏函数之前:<NSThread: 0x6000004c13c0>{number = 1, name = main}

//        2018-10-24 20:43:12.156237+0800 dispatch_barrier_sync[19254:2065850] 耗时回调任务1:<NSThread: 0x60000049a7c0>{number = 3, name = (null)}

//        2018-10-24 20:43:12.156247+0800 dispatch_barrier_sync[19254:2065848] 耗时回调任务2:<NSThread: 0x6000004a52c0>{number = 4, name = (null)}

//        2018-10-24 20:43:12.156531+0800 dispatch_barrier_sync[19254:2065765] 我在异步栅栏函数之后:<NSThread: 0x6000004c13c0>{number = 1, name = main}

//        2018-10-24 20:43:12.162173+0800 dispatch_barrier_sync[19254:2065848] 我是耗时回调的异步栅栏函数block块:<NSThread: 0x6000004a52c0>{number = 4, name = (null)}

//        2018-10-24 20:43:12.163108+0800 dispatch_barrier_sync[19254:2065848] 耗时回调任务3:<NSThread: 0x6000004a52c0>{number = 4, name = (null)}

//        2018-10-24 20:43:12.163157+0800 dispatch_barrier_sync[19254:2065850] 耗时回调任务4:<NSThread: 0x60000049a7c0>{number = 3, name = (null)}

//        2018-10-24 20:43:12.249516+0800 dispatch_barrier_sync[19254:2065850] 请求2返回了

//        2018-10-24 20:43:12.250501+0800 dispatch_barrier_sync[19254:2065848] 请求1返回了

//        2018-10-24 20:43:12.251126+0800 dispatch_barrier_sync[19254:2065848] 请求zl返回了

//        2018-10-24 20:43:12.251694+0800 dispatch_barrier_sync[19254:2065848] 请求4返回了

//        2018-10-24 20:43:12.252295+0800 dispatch_barrier_sync[19254:2065848] 请求3返回了

//    }

        //异步栅栏函数,前边的打印、栅栏函数block内的任务、后边的打印都在主线程 同步

}

通过例3、例4的打印可以看出无论是同步还是异步栅栏函数,调用这个函数总是在barrier block被提交之后立即返回,不会等到block被执行。

网传栅栏函数的正确用法只能用于并行队列,用于串行或全局队列,就不能起到栅栏的作用了,此时的栅栏函数相当于同步函数dispatch_sync。

于是,我试了试一下组合:

1、同步栅栏函数 + 全局队列;通过示例代码发现:与同步栅栏函数 + 并行队列 打印效果一样。。。(在这先打个问号,有高见者情留言)

2、异步栅栏函数 + 全局队列;通过示例代码发现:与异步栅栏函数 + 并行队列 打印效果一样。。。(在这先打个问号,有高见者请留言)

3、同步栅栏函数 + 串行队列;通过示例代码发现:各任务间在同一线程,顺序执行,此处用栅栏函数无意义

4、同步栅栏函数 + 串行队列;通过示例代码发现:各任务间在同一线程,顺序执行,此处用栅栏函数无意义

栅栏函数的用途:

栅栏函数不能保证有回调的任务的执行顺序,不能用于b请求依赖a请求回调的多请求案例,只适用于内部无block的任务。可以做读写锁:1、在没有写操作时,可以任意并发读取;2、在所有读操作完成后才进行写操作,写操作不能并发,且在写操作中,不能读取;3、写操作完后,又能并发读了

示例代码:

https://download.csdn.net/download/denggun12345/10743703

猜你喜欢

转载自blog.csdn.net/denggun12345/article/details/83375990