GCD全解-dispatch_barrier_sync/async-栅栏函数

简介: GCD全解-dispatch_barrier_sync/async-栅栏函数

前言


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


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


函数说明:


# 栅栏函数仅与并发队列(DISPATCH_QUEUE_CONCURRENT)有效,
/** 同步执行,栅栏效果仅对队列里面的代码有效
* @param queue 自定义并发队列
* @param block 代码块回调
*/
void dispatch_barrier_sync(dispatch_queue_t queue, DISPATCH_NOESCAPE dispatch_block_t block);
/** 异步执行,栅栏效果仅对队列里面的代码有效
* @param queue 自定义并发队列
* @param block 代码块回调
*/
void dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);
2、同步栅栏函数:dispatch_barrier_sync
- (void)testCustomBarrierSync {
    dispatch_queue_t currentQueue = dispatch_queue_create("barrierSyncQueue", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"======================= Before 11");
    dispatch_async(currentQueue, ^{
        sleep(0.1);
        NSLog(@"11 =======================");
    });
    NSLog(@"======================= Before 22");
    dispatch_async(currentQueue, ^{
        sleep(0.1);
        NSLog(@"22 =======================");
    });
    NSLog(@"======================= Before 33");
    dispatch_async(currentQueue, ^{
        sleep(0.1);
        NSLog(@"33 ==========");
    });
    NSLog(@"======================= Before 44");
    dispatch_barrier_sync(currentQueue, ^{
        sleep(0.1);
        NSLog(@"In sync barrier =======");
    });
    NSLog(@"======================= After 11");
    dispatch_async(currentQueue, ^{
        sleep(0.1);
        NSLog(@"44 =======================");
    });
    NSLog(@"======================= After 22");
    dispatch_async(currentQueue, ^{
        sleep(0.1);
        NSLog(@"55 =======================");
    });
    NSLog(@"======================= After 33");
}


打印结果:


睡眠0.5秒第1次打印:


2021-02-22 10:05:05.079629+0800 TestDemo[17503:9024036] ======================= Before 11
2021-02-22 10:05:05.079691+0800 TestDemo[17503:9024036] ======================= Before 22
2021-02-22 10:05:05.079699+0800 TestDemo[17503:9024273] 11 ====================
2021-02-22 10:05:05.079737+0800 TestDemo[17503:9024036] ======================= Before 33
2021-02-22 10:05:05.079742+0800 TestDemo[17503:9024445] 22 ====================
2021-02-22 10:05:05.079813+0800 TestDemo[17503:9024036] ======================= Before 44
2021-02-22 10:05:05.079837+0800 TestDemo[17503:9024456] 33 ====================
2021-02-22 10:05:05.080298+0800 TestDemo[17503:9024036] In sync barrier =======
2021-02-22 10:05:05.080404+0800 TestDemo[17503:9024036] ======================= After 11
2021-02-22 10:05:05.080542+0800 TestDemo[17503:9024036] ======================= After 22
2021-02-22 10:05:05.080552+0800 TestDemo[17503:9024446] 44 ====================
2021-02-22 10:05:05.080770+0800 TestDemo[17503:9024036] ======================= After 33
2021-02-22 10:05:05.080779+0800 TestDemo[17503:9024273] 55 ====================


睡眠0.5秒第2次打印:


2021-02-22 10:40:19.890124+0800 TestDemo[17585:9037449] ======================= Before 11
2021-02-22 10:40:19.890177+0800 TestDemo[17585:9037449] ======================= Before 22
2021-02-22 10:40:19.890200+0800 TestDemo[17585:9037449] ======================= Before 33
2021-02-22 10:40:19.890212+0800 TestDemo[17585:9038004] 11 ====================
2021-02-22 10:40:19.890220+0800 TestDemo[17585:9037449] ======================= Before 44
2021-02-22 10:40:19.890237+0800 TestDemo[17585:9038004] 22 ====================
2021-02-22 10:40:19.890252+0800 TestDemo[17585:9037701] 33 ====================
2021-02-22 10:40:19.890590+0800 TestDemo[17585:9037449] In sync barrier =======
2021-02-22 10:40:19.890691+0800 TestDemo[17585:9037449] ======================= After 11
2021-02-22 10:40:19.890810+0800 TestDemo[17585:9037449] ======================= After 22
2021-02-22 10:40:19.890834+0800 TestDemo[17585:9037701] 44 ====================
2021-02-22 10:40:19.890918+0800 TestDemo[17585:9037449] ======================= After 33
2021-02-22 10:40:19.890948+0800 TestDemo[17585:9037925] 55 ====================


睡眠1秒:


2021-02-22 10:46:16.967080+0800 TestDemo[17596:9039511] ======================= Before 11
2021-02-22 10:46:16.967159+0800 TestDemo[17596:9039511] ======================= Before 22
2021-02-22 10:46:16.967188+0800 TestDemo[17596:9039511] ======================= Before 33
2021-02-22 10:46:16.967214+0800 TestDemo[17596:9039511] ======================= Before 44
2021-02-22 10:46:17.971862+0800 TestDemo[17596:9039717] 22 ====================
2021-02-22 10:46:17.971862+0800 TestDemo[17596:9039707] 33 ====================
2021-02-22 10:46:17.971862+0800 TestDemo[17596:9040111] 11 ====================
2021-02-22 10:46:18.973297+0800 TestDemo[17596:9039511] In sync barrier =======
2021-02-22 10:46:18.973754+0800 TestDemo[17596:9039511] ======================= After 11
2021-02-22 10:46:18.974047+0800 TestDemo[17596:9039511] ======================= After 22
2021-02-22 10:46:18.974258+0800 TestDemo[17596:9039511] ======================= After 33
2021-02-22 10:46:19.978829+0800 TestDemo[17596:9040111] 44 ====================
2021-02-22 10:46:19.979040+0800 TestDemo[17596:9039717] 55 ====================


结论:

需要等待栅栏执行完才会执行栅栏后面的任务,甚至包括队列之外的函数。


2、异步栅栏函数:dispatch_barrier_async


- (void)testCustomBarrierAsync {
    dispatch_queue_t currentQueue = dispatch_queue_create("barrierAsyncQueue", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"=========================== Before 111");
    dispatch_async(currentQueue, ^{
        sleep(0.5);
        NSLog(@"111 =======================");
    });
    NSLog(@"=========================== Before 222");
    dispatch_async(currentQueue, ^{
        sleep(0.5);
        NSLog(@"222 =======================");
    });
    NSLog(@"=========================== Before 333");
    dispatch_async(currentQueue, ^{
        sleep(0.5);
        NSLog(@"333 =======================");
    });
    NSLog(@"=========================== Before 444");
    dispatch_barrier_async(currentQueue, ^{
        sleep(0.5);
        NSLog(@"In async barrier ==========");
    });
    NSLog(@"=========================== After 111");
    dispatch_async(currentQueue, ^{
        sleep(0.5);
        NSLog(@"444 =======================");
    });
    NSLog(@"=========================== After 222");
    dispatch_async(currentQueue, ^{
        sleep(0.5);
        NSLog(@"555 =======================");
    });
    NSLog(@"=========================== After 333");
}


睡眠0.5秒时第1次打印:


2021-02-22 10:27:54.280318+0800 TestDemo[17561:9033089] =========================== Before 111
2021-02-22 10:27:54.280383+0800 TestDemo[17561:9033089] =========================== Before 222
2021-02-22 10:27:54.280400+0800 TestDemo[17561:9033430] 111 =======================
2021-02-22 10:27:54.280411+0800 TestDemo[17561:9033089] =========================== Before 333
2021-02-22 10:27:54.280433+0800 TestDemo[17561:9033430] 222 =======================
2021-02-22 10:27:54.280437+0800 TestDemo[17561:9033089] =========================== Before 444
2021-02-22 10:27:54.280457+0800 TestDemo[17561:9033303] 333 =======================
2021-02-22 10:27:54.280490+0800 TestDemo[17561:9033089] =========================== After 111
2021-02-22 10:27:54.280505+0800 TestDemo[17561:9033303] In async barrier ==========
2021-02-22 10:27:54.280682+0800 TestDemo[17561:9033089] =========================== After 222
2021-02-22 10:27:54.280811+0800 TestDemo[17561:9033089] =========================== After 333
2021-02-22 10:27:54.281040+0800 TestDemo[17561:9033303] 444 =======================
2021-02-22 10:27:54.281062+0800 TestDemo[17561:9033430] 555 =======================


睡眠0.5秒时第2次打印:


2021-02-22 10:28:46.768469+0800 TestDemo[17561:9033089] =========================== Before 111
2021-02-22 10:28:46.768525+0800 TestDemo[17561:9033089] =========================== Before 222
2021-02-22 10:28:46.768548+0800 TestDemo[17561:9033313] 111 =======================
2021-02-22 10:28:46.768556+0800 TestDemo[17561:9033089] =========================== Before 333
2021-02-22 10:28:46.768594+0800 TestDemo[17561:9033089] =========================== Before 444
2021-02-22 10:28:46.768599+0800 TestDemo[17561:9033536] 222 =======================
2021-02-22 10:28:46.768635+0800 TestDemo[17561:9033089] =========================== After 111
2021-02-22 10:28:46.768691+0800 TestDemo[17561:9033313] 333 =======================
2021-02-22 10:28:46.768728+0800 TestDemo[17561:9033089] =========================== After 222
2021-02-22 10:28:46.768900+0800 TestDemo[17561:9033089] =========================== After 333
2021-02-22 10:28:46.769484+0800 TestDemo[17561:9033313] In async barrier ==========
2021-02-22 10:28:46.769584+0800 TestDemo[17561:9033313] 444 =======================
2021-02-22 10:28:46.769607+0800 TestDemo[17561:9033778] 555 =======================


睡眠1秒时:


2021-02-22 10:21:54.511690+0800 TestDemo[17540:9030197] =========================== Before 111
2021-02-22 10:21:54.511790+0800 TestDemo[17540:9030197] =========================== Before 222
2021-02-22 10:21:54.511820+0800 TestDemo[17540:9030197] =========================== Before 333
2021-02-22 10:21:54.511849+0800 TestDemo[17540:9030197] =========================== Before 444
2021-02-22 10:21:54.511874+0800 TestDemo[17540:9030197] =========================== After 111
2021-02-22 10:21:54.511899+0800 TestDemo[17540:9030197] =========================== After 222
2021-02-22 10:21:54.511922+0800 TestDemo[17540:9030197] =========================== After 333
2021-02-22 10:21:55.516901+0800 TestDemo[17540:9030520] 111 =======================
2021-02-22 10:21:55.516901+0800 TestDemo[17540:9030427] 222 =======================
2021-02-22 10:21:55.516916+0800 TestDemo[17540:9030467] 333 =======================
2021-02-22 10:21:56.522624+0800 TestDemo[17540:9030520] In async barrier ==========
2021-02-22 10:21:57.523760+0800 TestDemo[17540:9030427] 555 =======================
2021-02-22 10:21:57.528231+0800 TestDemo[17540:9030520] 444 =======================


4、总结分析


1、现象:dispatch_barrier_sync 需要等待栅栏执行完才会执行栅栏后面的任务,而dispatch_barrier_async 无需等待栅栏执行完,会继续往下走(保留在队列里)。

2、原因:同步栅栏执行的任务在同一个线程中,而异步栅栏执行队列任务时,另外开辟了一个子线程,独立存在。

4、共同点:a、等待在它前面插入队列的任务先执行完。b、等待他们自己的任务执行完再执行后面的任务。


5、栅栏函数 与 自定义并发队列


1、栅栏函数仅对自定义并发队列(DISPATCH_QUEUE_CONCURRENT)才会有栅栏的作用。

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

2、另外,全局并发队列是系统创建,苹果有时候会在全局并发队列中处理它自有任务。使用栅栏函数阻塞全局并发队列无效。

3、针对dispatch_barrier_sync 如果你传入的是串行或全局并发队列 则它的作用和 dispatch_sync 一样; 如果是 dispatch_barrier_async 则它的作用和 dispatch_async一样。


4、官方说明:栅栏函数的队列创建务必使用 dispatch_queue_create 函数创建的并发队列。如果传递给此函数的队列是串行队列或全局并发队列之一,则此函数的行为类似于dispatch_sync函数。


相关文章
|
缓存 Unix iOS开发
iOS Crash 分析攻略
应用崩溃是影响 APP 体验的重要一环, 而崩溃定位也常常让开发者头疼。本文就讲讲关于 Crash 分析的那些事。
3965 0
iOS Crash 分析攻略
|
存储 数据可视化 C语言
[iOS研习记]聊聊iOS中的Mach-O
Mach-O的全称为Mach Object,是OS X与iOS上的一种可执行文件格式。Mach本身指一种操作系统的微内核标准,被用于OS X与iOS系统的内核中。相信对于移动端的iOS开发者来说,对Mach-O文件一定不陌生,我们编译打包的iOS IPA文件,内部其实就有一个可执行的Mach-O文件,我们开发的framework和.a等动态库静态库中,也会包含Mach-O文件,本篇文章,我们就来详细看看Mach-O中究竟放的是什么,Mach-O的结构是怎样的。
1100 0
|
安全 iOS开发
iOS页面布局:UIScrollView的布局问题
iOS页面布局:UIScrollView的布局问题
543 63
|
11月前
|
运维 监控 BI
卓越架构之FinOps最佳实践
本文探讨了云成本管理的趋势和FinOps的最佳实践。随着云计算的普及,传统的IT管理模式已无法适应按需使用和按量付费的新模式,导致企业面临资源浪费和成本失控的风险。FinOps作为一种管理理念,强调运维、财务和技术团队的合作,通过数据驱动和业务价值驱动的方式优化云成本。文章介绍了FinOps的核心挑战、最佳实践及技术工具的应用,帮助企业有效管理和优化云成本,实现降本增效。
|
人工智能 JSON 前端开发
copy和strong的区别及使用不当引起的crash
copy和strong的区别及使用不当引起的crash
288 0
|
关系型数据库 MySQL Linux
一文教会你如何在Linux系统中使用Docker安装Mysql 5.7版本 【详细过程+图解】
这篇文章提供了在Linux系统中使用Docker安装Mysql 5.7版本的详细过程和图解,包括安装指定版本、创建实例、启动、使用Navicat连接测试、文件挂载与端口映射、进入容器、配置文件修改以及重新启动容器等步骤。
一文教会你如何在Linux系统中使用Docker安装Mysql 5.7版本 【详细过程+图解】
|
Java jenkins Linux
Linux安装Jenkins(Java11最新版)
Linux安装Jenkins(Java11最新版)
Linux安装Jenkins(Java11最新版)
|
安全 数据安全/隐私保护 iOS开发
iOS 动态权限管理:向用户索取相机和相册访问权限
【4月更文挑战第16天】 在移动应用开发中,尤其是针对iOS平台,用户隐私保护已成为不可忽视的要素。随着苹果对隐私政策的不断收紧,如何优雅地向用户请求访问其设备上敏感资源的权限,成为了开发者必须面对的挑战。本文将深入探讨如何在iOS应用中实现动态权限管理,重点讨论相机和相册访问权限的请求过程,并指导读者通过编程方式提升用户体验与满足数据保护规范之间的平衡。
|
Java 程序员 数据安全/隐私保护
Java接口签名(Signature)实现方案
针对当前的系统开发一个对外开放的接口
|
机器学习/深度学习 JSON Linux
NSLog日志输出不全问题分析与解决方案
NSLog日志输出不全问题分析与解决方案
527 0
下一篇
oss云网关配置