用示例阐明 GCD 的同步异步串行并行
[TOC]
示例
-
下文示例中所用到的宏定义有:
GCD_TEST_LOG(task)
NSLog(@"task:%@ main:%@ p:%p", task, NSThread.isMainThread ? @"1" : @"0", NSThread.currentThread)
GCD_TEST_TASK_A
GCD_TEST_LOG(@"A"); NSLog(@"1"); [NSThread sleepForTimeInterval:1.f]; NSLog(@"2")
GCD_TEST_TASK_B
GCD_TEST_LOG(@"B"); NSLog(@"4"); [NSThread sleepForTimeInterval:1.f]; NSLog(@"5")
GCD_TEST_TASK_C
GCD_TEST_LOG(@"C"); NSLog(@"7"); [NSThread sleepForTimeInterval:1.f]; NSLog(@"8")
GCD_TEST_TASK_D
GCD_TEST_LOG(@"D"); NSLog(@"10"); [NSThread sleepForTimeInterval:1.f]; NSLog(@"11")
下文示例代码在主线程中执行.
-
下文所用符号示意:
✅ 较常用.
⚠️ 极少使用, 或使用有风险, 或使用无意义.
-
为方便复制调试, 以上宏定义源码如下:
#define GCD_TEST_LOG(task) NSLog(@"task:%@ main:%@ p:%p", task, NSThread.isMainThread ? @"1" : @"0", NSThread.currentThread) #define GCD_TEST_TASK_A \ GCD_TEST_LOG(@"A"); \ NSLog(@"1"); \ [NSThread sleepForTimeInterval:1.f]; \ NSLog(@"2") #define GCD_TEST_TASK_B \ GCD_TEST_LOG(@"B"); \ NSLog(@"4"); \ [NSThread sleepForTimeInterval:1.f]; \ NSLog(@"5") #define GCD_TEST_TASK_C \ GCD_TEST_LOG(@"C"); \ NSLog(@"7"); \ [NSThread sleepForTimeInterval:1.f]; \ NSLog(@"8") #define GCD_TEST_TASK_D \ GCD_TEST_LOG(@"D"); \ NSLog(@"10"); \ [NSThread sleepForTimeInterval:1.f]; \ NSLog(@"11")
main_queue
dispatch_sync ⚠️
dispatch_queue_t main_queue = dispatch_get_main_queue();
dispatch_sync(main_queue, ^{ GCD_TEST_TASK_A; }); // 1 | 2
NSLog(@"3"); // 3
dispatch_sync(main_queue, ^{ GCD_TEST_TASK_B; }); // 4 | 5
NSLog(@"6"); // 6
dispatch_sync(main_queue, ^{ GCD_TEST_TASK_C; }); // 7 | 8
NSLog(@"9"); // 9
dispatch_sync(main_queue, ^{ GCD_TEST_TASK_D; }); // 10 | 11
NSLog(@"12"); // 12
输出
无
崩溃在第 2 行
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
如在其它线程执行以上代码, 则正常执行. 如下:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_queue_t main_queue = dispatch_get_main_queue();
dispatch_sync(main_queue, ^{ GCD_TEST_TASK_A; }); // 1 | 2
NSLog(@"3"); // 3
dispatch_sync(main_queue, ^{ GCD_TEST_TASK_B; }); // 4 | 5
NSLog(@"6"); // 6
dispatch_sync(main_queue, ^{ GCD_TEST_TASK_C; }); // 7 | 8
NSLog(@"9"); // 9
dispatch_sync(main_queue, ^{ GCD_TEST_TASK_D; }); // 10 | 11
NSLog(@"12"); // 12
});
输出
2017-02-11 17:59:28.471943+0800 sun[68420:10866547] task:A main:1 p:0x600001449f40
2017-02-11 17:59:28.472160+0800 sun[68420:10866547] 1
2017-02-11 17:59:29.472686+0800 sun[68420:10866547] 2
2017-02-11 17:59:29.472918+0800 sun[68420:10866746] 3
2017-02-11 17:59:29.474518+0800 sun[68420:10866547] task:B main:1 p:0x600001449f40
2017-02-11 17:59:29.474743+0800 sun[68420:10866547] 4
2017-02-11 17:59:30.475987+0800 sun[68420:10866547] 5
2017-02-11 17:59:30.476268+0800 sun[68420:10866746] 6
2017-02-11 17:59:30.476631+0800 sun[68420:10866547] task:C main:1 p:0x600001449f40
2017-02-11 17:59:30.476804+0800 sun[68420:10866547] 7
2017-02-11 17:59:31.478109+0800 sun[68420:10866547] 8
2017-02-11 17:59:31.478349+0800 sun[68420:10866746] 9
2017-02-11 17:59:31.478600+0800 sun[68420:10866547] task:D main:1 p:0x600001449f40
2017-02-11 17:59:31.478784+0800 sun[68420:10866547] 10
2017-02-11 17:59:32.480031+0800 sun[68420:10866547] 11
2017-02-11 17:59:32.480304+0800 sun[68420:10866746] 12
dispatch_async ✅
dispatch_queue_t main_queue = dispatch_get_main_queue();
dispatch_async(main_queue, ^{ GCD_TEST_TASK_A; }); // 1 | 2
NSLog(@"3"); // 3
dispatch_async(main_queue, ^{ GCD_TEST_TASK_B; }); // 4 | 5
NSLog(@"6"); // 6
dispatch_async(main_queue, ^{ GCD_TEST_TASK_C; }); // 7 | 8
NSLog(@"9"); // 9
dispatch_async(main_queue, ^{ GCD_TEST_TASK_D; }); // 10 | 11
NSLog(@"12"); // 12
输出
2017-02-11 18:00:19.191572+0800 sun[68464:10868282] 3
2017-02-11 18:00:19.191773+0800 sun[68464:10868282] 6
2017-02-11 18:00:19.191927+0800 sun[68464:10868282] 9
2017-02-11 18:00:19.192077+0800 sun[68464:10868282] 12
2017-02-11 18:00:19.192433+0800 sun[68464:10868282] task:A main:1 p:0x6000028cdf40
2017-02-11 18:00:19.192569+0800 sun[68464:10868282] 1
2017-02-11 18:00:20.193589+0800 sun[68464:10868282] 2
2017-02-11 18:00:20.193928+0800 sun[68464:10868282] task:B main:1 p:0x6000028cdf40
2017-02-11 18:00:20.194083+0800 sun[68464:10868282] 4
2017-02-11 18:00:21.194587+0800 sun[68464:10868282] 5
2017-02-11 18:00:21.194946+0800 sun[68464:10868282] task:C main:1 p:0x6000028cdf40
2017-02-11 18:00:21.195064+0800 sun[68464:10868282] 7
2017-02-11 18:00:22.195342+0800 sun[68464:10868282] 8
2017-02-11 18:00:22.195688+0800 sun[68464:10868282] task:D main:1 p:0x6000028cdf40
2017-02-11 18:00:22.195850+0800 sun[68464:10868282] 10
2017-02-11 18:00:23.197078+0800 sun[68464:10868282] 11
global_queue
dispatch_sync ⚠️
dispatch_queue_t global_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_sync(global_queue, ^{ GCD_TEST_TASK_A; }); // 1 | 2
NSLog(@"3"); // 3
dispatch_sync(global_queue, ^{ GCD_TEST_TASK_B; }); // 4 | 5
NSLog(@"6"); // 6
dispatch_sync(global_queue, ^{ GCD_TEST_TASK_C; }); // 7 | 8
NSLog(@"9"); // 9
dispatch_sync(global_queue, ^{ GCD_TEST_TASK_D; }); // 10 | 11
NSLog(@"12"); // 12
输出
2017-02-11 18:01:21.071692+0800 sun[68510:10869926] task:A main:1 p:0x600002912a40
2017-02-11 18:01:21.071854+0800 sun[68510:10869926] 1
2017-02-11 18:01:22.073179+0800 sun[68510:10869926] 2
2017-02-11 18:01:22.073418+0800 sun[68510:10869926] 3
2017-02-11 18:01:22.073596+0800 sun[68510:10869926] task:B main:1 p:0x600002912a40
2017-02-11 18:01:22.073717+0800 sun[68510:10869926] 4
2017-02-11 18:01:23.074995+0800 sun[68510:10869926] 5
2017-02-11 18:01:23.075236+0800 sun[68510:10869926] 6
2017-02-11 18:01:23.075391+0800 sun[68510:10869926] task:C main:1 p:0x600002912a40
2017-02-11 18:01:23.075554+0800 sun[68510:10869926] 7
2017-02-11 18:01:24.076513+0800 sun[68510:10869926] 8
2017-02-11 18:01:24.076904+0800 sun[68510:10869926] 9
2017-02-11 18:01:24.077053+0800 sun[68510:10869926] task:D main:1 p:0x600002912a40
2017-02-11 18:01:24.077247+0800 sun[68510:10869926] 10
2017-02-11 18:01:25.078505+0800 sun[68510:10869926] 11
2017-02-11 18:01:25.078753+0800 sun[68510:10869926] 12
dispatch_async ✅
dispatch_queue_t global_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(global_queue, ^{ GCD_TEST_TASK_A; }); // 1 | 2
NSLog(@"3"); // 3
dispatch_async(global_queue, ^{ GCD_TEST_TASK_B; }); // 4 | 5
NSLog(@"6"); // 6
dispatch_async(global_queue, ^{ GCD_TEST_TASK_C; }); // 7 | 8
NSLog(@"9"); // 9
dispatch_async(global_queue, ^{ GCD_TEST_TASK_D; }); // 10 | 11
NSLog(@"12"); // 12
输出
2017-02-11 18:02:06.159847+0800 sun[68554:10871641] 3
2017-02-11 18:02:06.159892+0800 sun[68554:10871805] task:A main:0 p:0x60000163a2c0
2017-02-11 18:02:06.160052+0800 sun[68554:10871641] 6
2017-02-11 18:02:06.160065+0800 sun[68554:10871805] 1
2017-02-11 18:02:06.160098+0800 sun[68554:10871784] task:B main:0 p:0x60000190ec80
2017-02-11 18:02:06.160241+0800 sun[68554:10871641] 9
2017-02-11 18:02:06.160247+0800 sun[68554:10871784] 4
2017-02-11 18:02:06.160263+0800 sun[68554:10871797] task:C main:0 p:0x600001639dc0
2017-02-11 18:02:06.160404+0800 sun[68554:10871641] 12
2017-02-11 18:02:06.160439+0800 sun[68554:10871787] task:D main:0 p:0x60000165e080
2017-02-11 18:02:06.161688+0800 sun[68554:10871787] 10
2017-02-11 18:02:06.161892+0800 sun[68554:10871797] 7
2017-02-11 18:02:07.160298+0800 sun[68554:10871805] 2
2017-02-11 18:02:07.160484+0800 sun[68554:10871784] 5
2017-02-11 18:02:07.166661+0800 sun[68554:10871787] 11
2017-02-11 18:02:07.166676+0800 sun[68554:10871797] 8
custom_queue
DISPATCH_QUEUE_SERIAL
dispatch_sync ⚠️
dispatch_queue_t custom_queue = dispatch_queue_create("custom_queue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(custom_queue, ^{ GCD_TEST_TASK_A; }); // 1 | 2
NSLog(@"3"); // 3
dispatch_sync(custom_queue, ^{ GCD_TEST_TASK_B; }); // 4 | 5
NSLog(@"6"); // 6
dispatch_sync(custom_queue, ^{ GCD_TEST_TASK_C; }); // 7 | 8
NSLog(@"9"); // 9
dispatch_sync(custom_queue, ^{ GCD_TEST_TASK_D; }); // 10 | 11
NSLog(@"12"); // 12
输出
2017-02-11 18:02:46.126540+0800 sun[68594:10873135] task:A main:1 p:0x600001657880
2017-02-11 18:02:46.126753+0800 sun[68594:10873135] 1
2017-02-11 18:02:47.128070+0800 sun[68594:10873135] 2
2017-02-11 18:02:47.128445+0800 sun[68594:10873135] 3
2017-02-11 18:02:47.128615+0800 sun[68594:10873135] task:B main:1 p:0x600001657880
2017-02-11 18:02:47.128740+0800 sun[68594:10873135] 4
2017-02-11 18:02:48.129982+0800 sun[68594:10873135] 5
2017-02-11 18:02:48.130324+0800 sun[68594:10873135] 6
2017-02-11 18:02:48.130498+0800 sun[68594:10873135] task:C main:1 p:0x600001657880
2017-02-11 18:02:48.130619+0800 sun[68594:10873135] 7
2017-02-11 18:02:49.131752+0800 sun[68594:10873135] 8
2017-02-11 18:02:49.131942+0800 sun[68594:10873135] 9
2017-02-11 18:02:49.132027+0800 sun[68594:10873135] task:D main:1 p:0x600001657880
2017-02-11 18:02:49.132119+0800 sun[68594:10873135] 10
2017-02-11 18:02:50.132608+0800 sun[68594:10873135] 11
2017-02-11 18:02:50.132791+0800 sun[68594:10873135] 12
dispatch_async ✅
dispatch_queue_t custom_queue = dispatch_queue_create("custom_queue", DISPATCH_QUEUE_SERIAL);
dispatch_async(custom_queue, ^{ GCD_TEST_TASK_A; }); // 1 | 2
NSLog(@"3"); // 3
dispatch_async(custom_queue, ^{ GCD_TEST_TASK_B; }); // 4 | 5
NSLog(@"6"); // 6
dispatch_async(custom_queue, ^{ GCD_TEST_TASK_C; }); // 7 | 8
NSLog(@"9"); // 9
dispatch_async(custom_queue, ^{ GCD_TEST_TASK_D; }); // 10 | 11
NSLog(@"12"); // 12
输出
2017-02-11 18:03:31.083347+0800 sun[68633:10874631] 3
2017-02-11 18:03:31.083393+0800 sun[68633:10874809] task:A main:0 p:0x600000d71800
2017-02-11 18:03:31.083545+0800 sun[68633:10874631] 6
2017-02-11 18:03:31.083569+0800 sun[68633:10874809] 1
2017-02-11 18:03:31.083704+0800 sun[68633:10874631] 9
2017-02-11 18:03:31.083910+0800 sun[68633:10874631] 12
2017-02-11 18:03:32.085991+0800 sun[68633:10874809] 2
2017-02-11 18:03:32.086343+0800 sun[68633:10874809] task:B main:0 p:0x600000d71800
2017-02-11 18:03:32.086501+0800 sun[68633:10874809] 4
2017-02-11 18:03:33.087598+0800 sun[68633:10874809] 5
2017-02-11 18:03:33.087961+0800 sun[68633:10874809] task:C main:0 p:0x600000d71800
2017-02-11 18:03:33.088119+0800 sun[68633:10874809] 7
2017-02-11 18:03:34.091592+0800 sun[68633:10874809] 8
2017-02-11 18:03:34.091858+0800 sun[68633:10874809] task:D main:0 p:0x600000d71800
2017-02-11 18:03:34.092052+0800 sun[68633:10874809] 10
2017-02-11 18:03:35.096494+0800 sun[68633:10874809] 11
DISPATCH_QUEUE_CONCURRENT
dispatch_sync ⚠️
等效 global_queue | dispatch_sync
dispatch_queue_t custom_queue = dispatch_queue_create("custom_queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(custom_queue, ^{ GCD_TEST_TASK_A; }); // 1 | 2
NSLog(@"3"); // 3
dispatch_sync(custom_queue, ^{ GCD_TEST_TASK_B; }); // 4 | 5
NSLog(@"6"); // 6
dispatch_sync(custom_queue, ^{ GCD_TEST_TASK_C; }); // 7 | 8
NSLog(@"9"); // 9
dispatch_sync(custom_queue, ^{ GCD_TEST_TASK_D; }); // 10 | 11
NSLog(@"12"); // 12
输出
2017-02-11 18:04:13.914992+0800 sun[68678:10876152] task:A main:1 p:0x600000de6a80
2017-02-11 18:04:13.915168+0800 sun[68678:10876152] 1
2017-02-11 18:04:14.915620+0800 sun[68678:10876152] 2
2017-02-11 18:04:14.915822+0800 sun[68678:10876152] 3
2017-02-11 18:04:14.915926+0800 sun[68678:10876152] task:B main:1 p:0x600000de6a80
2017-02-11 18:04:14.916103+0800 sun[68678:10876152] 4
2017-02-11 18:04:15.916831+0800 sun[68678:10876152] 5
2017-02-11 18:04:15.917190+0800 sun[68678:10876152] 6
2017-02-11 18:04:15.917319+0800 sun[68678:10876152] task:C main:1 p:0x600000de6a80
2017-02-11 18:04:15.917427+0800 sun[68678:10876152] 7
2017-02-11 18:04:16.918675+0800 sun[68678:10876152] 8
2017-02-11 18:04:16.918918+0800 sun[68678:10876152] 9
2017-02-11 18:04:16.919083+0800 sun[68678:10876152] task:D main:1 p:0x600000de6a80
2017-02-11 18:04:16.919277+0800 sun[68678:10876152] 10
2017-02-11 18:04:17.920562+0800 sun[68678:10876152] 11
2017-02-11 18:04:17.920799+0800 sun[68678:10876152] 12
dispatch_async ✅
等效 global_queue| dispatch_async
dispatch_queue_t custom_queue = dispatch_queue_create("custom_queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(custom_queue, ^{ GCD_TEST_TASK_A; }); // 1 | 2
NSLog(@"3"); // 3
dispatch_async(custom_queue, ^{ GCD_TEST_TASK_B; }); // 4 | 5
NSLog(@"6"); // 6
dispatch_async(custom_queue, ^{ GCD_TEST_TASK_C; }); // 7 | 8
NSLog(@"9"); // 9
dispatch_async(custom_queue, ^{ GCD_TEST_TASK_D; }); // 10 | 11
NSLog(@"12"); // 12
输出
2017-02-11 18:04:53.590727+0800 sun[68716:10877557] 3
2017-02-11 18:04:53.590749+0800 sun[68716:10877625] task:A main:0 p:0x6000022c4d80
2017-02-11 18:04:53.590956+0800 sun[68716:10877557] 6
2017-02-11 18:04:53.590976+0800 sun[68716:10877625] 1
2017-02-11 18:04:53.590980+0800 sun[68716:10877635] task:B main:0 p:0x6000022afd00
2017-02-11 18:04:53.591153+0800 sun[68716:10877557] 9
2017-02-11 18:04:53.591198+0800 sun[68716:10877639] task:C main:0 p:0x6000022b25c0
2017-02-11 18:04:53.591205+0800 sun[68716:10877635] 4
2017-02-11 18:04:53.591335+0800 sun[68716:10877557] 12
2017-02-11 18:04:53.591379+0800 sun[68716:10877639] 7
2017-02-11 18:04:53.591403+0800 sun[68716:10877641] task:D main:0 p:0x6000022c5c80
2017-02-11 18:04:53.592740+0800 sun[68716:10877641] 10
2017-02-11 18:04:54.593739+0800 sun[68716:10877625] 2
2017-02-11 18:04:54.593756+0800 sun[68716:10877639] 8
2017-02-11 18:04:54.593756+0800 sun[68716:10877635] 5
2017-02-11 18:04:54.593756+0800 sun[68716:10877641] 11
总结
总结只有一点, 个人认为这一点是理解 线程
上的 任务
及 任务串行并行
的核心要点. 而 dispatch_sync
和 dispatch_async
则是在某一 线程
下调度某一 线程队列
的行为, 其行为是 平行
和 相对
的.
-
dispatch_sync
或dispatch_async
都是相对当前线程, 死锁与否都是相对当前添加任务所在线程.
对于任务的串行并行, 无需再赘述.