美文网首页
用示例阐明 GCD 的同步异步串行并行

用示例阐明 GCD 的同步异步串行并行

作者: CoderSun | 来源:发表于2019-05-28 18:42 被阅读0次

    用示例阐明 GCD 的同步异步串行并行

    [TOC]

    示例

    1. 下文示例中所用到的宏定义有:

      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")
      
    2. 下文示例代码在主线程中执行.

    3. 下文所用符号示意:

      ✅ 较常用.

      ⚠️ 极少使用, 或使用有风险, 或使用无意义.

    4. 为方便复制调试, 以上宏定义源码如下:

      #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_syncdispatch_async 则是在某一 线程 下调度某一 线程队列 的行为, 其行为是 平行相对 的.

    1. dispatch_syncdispatch_async 都是相对当前线程, 死锁与否都是相对当前添加任务所在线程.

    对于任务的串行并行, 无需再赘述.

    相关文章

      网友评论

          本文标题:用示例阐明 GCD 的同步异步串行并行

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