前言
应用需求:假设有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函数。