将sync / async与串行/并发队列混合时,调度程序如何工作?

时间:2014-04-08 14:31:32

标签: ios asynchronous queue sync grand-central-dispatch

在Grand Central Dispatch中,当使用serial函数和concurrent函数时,调度程序如何使用不同的队列(dispatch_syncdispatch_async)?

1 个答案:

答案 0 :(得分:3)

首先,我们需要两种队列:一种序列和一种并发

dispatch_queue_t serialQueue =
dispatch_queue_create("com.matteogobbi.dispex.serial_queue", DISPATCH_QUEUE_SERIAL);

dispatch_queue_t concurrentQueue =
dispatch_queue_create("com.matteogobbi.dispex.concurrent_queue", DISPATCH_QUEUE_CONCURRENT);

因此,我们可以从第一个实验开始,使用串行队列和所有dispatch_async函数将我们的块添加到队列中:

/* Dispatch async with serial queue */
NSLog(@"\n\nDISPATCH: Async - QUEUE: Serial");

NSLog(@"block 1 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 1");
});

NSLog(@"block 2 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 2");
});

NSLog(@"block 3 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 3");
});

NSLog(@"block 4 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 4");
});

NSLog(@"block 5 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 5");
});

NSLog(@"block 6 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 6");
});

NSLog(@"block 7 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 7");
});

NSLog(@"block 8 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 8");
});

NSLog(@"block 9 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 9");
});

NSLog(@"block 10 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 10");
});

NSLog(@"ALL BLOCK ADDED TO THE QUEUE --> FUNCTION RETURNED");
  

DISPATCH:Async - QUEUE:Serial

     

2014-04-08 14:43:16.468 dispex [4346:60b]第1块补充

     

2014-04-08 14:43:16.468 dispex [4346:60b]第2块补充

     

2014-04-08 14:43:16.468 dispex [4346:1303]第1块

     

2014-04-08 14:43:16.469 dispex [4346:1303]第2块

     

2014-04-08 14:43:16.468 dispex [4346:60b]第3块补充

     

2014-04-08 14:43:16.469 dispex [4346:1303]第3块

     

2014-04-08 14:43:16.469 dispex [4346:60b]第4块补充

     

2014-04-08 14:43:16.469 dispex [4346:1303] block 4

     

2014-04-08 14:43:16.469 dispex [4346:60b]第5块补充

     

2014-04-08 14:43:16.470 dispex [4346:60b]第6块补充

     

2014-04-08 14:43:16.470 dispex [4346:1303]第5块

     

2014-04-08 14:43:16.471 dispex [4346:60b]第7块补充

     

2014-04-08 14:43:16.471 dispex [4346:1303]第6块

     

2014-04-08 14:43:16.471 dispex [4346:1303]第7块

     

2014-04-08 14:43:16.471 dispex [4346:60b]第8块补充

     

2014-04-08 14:43:16.471 dispex [4346:1303]第8块

     

2014-04-08 14:43:16.471 dispex [4346:60b]第9块补充

     

2014-04-08 14:43:16.472 dispex [4346:60b]第10块补充

     

2014-04-08 14:43:16.472 dispex [4346:1303]第9块

     

2014-04-08 14:43:16.472 dispex [4346:1303]第10块

     

2014-04-08 14:43:16.472 dispex [4346:60b]所有积木都加入了队列    - >功能返回

如您所见,该块已添加到队列中,但同时调度程序开始执行它们。这是dispatcher_async函数的一个特征,即将队列添加到队列而不等待它们完成执行。换句话说,如果在函数中使用dispatch_async,函数会立即返回,同时块正在执行。这非常有用!在这个例子中,我使用NSLog来报告何时将块添加到队列中,因此执行速度较慢并导致日志

  

所有已添加的块

最后。但正如我们将要看到的那样,没有日志,它将在开头写入。由于我们使用的是串行队列,因此按照添加顺序执行块。

下一步:

/* Just wait before begin with the next test */
dispatch_group_wait(group_async_serial, DISPATCH_TIME_FOREVER);


/* Dispatch sync with serial queue */
NSLog(@"\n\nDISPATCH: Sync - QUEUE: Serial");

NSLog(@"block 1 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 1");
});

NSLog(@"block 2 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 2");
});

NSLog(@"block 3 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 3");
});

NSLog(@"block 4 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 4");
});

NSLog(@"block 5 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 5");
});

NSLog(@"block 6 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 6");
});

NSLog(@"block 7 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 7");
});

NSLog(@"block 8 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 8");
});

NSLog(@"block 9 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 9");
});

NSLog(@"block 10 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 10");
});

NSLog(@"ALL BLOCK ADDED TO THE QUEUE --> FUNCTION RETURNED");
  

DISPATCH:Sync - QUEUE:Serial

     

2014-04-08 14:43:16.473 dispex [4346:60b]第1块补充

     

2014-04-08 14:43:16.474 dispex [4346:60b] block 1

     

2014-04-08 14:43:16.474 dispex [4346:60b]第2块补充

     

2014-04-08 14:43:16.474 dispex [4346:60b] block 2

     

2014-04-08 14:43:16.475 dispex [4346:60b]第3块补充

     

2014-04-08 14:43:16.475 dispex [4346:60b] block 3

     

2014-04-08 14:43:16.475 dispex [4346:60b]第4块补充

     

2014-04-08 14:43:16.475 dispex [4346:60b] block 4

     

2014-04-08 14:43:16.476 dispex [4346:60b]第5块补充

     

2014-04-08 14:43:16.476 dispex [4346:60b]第5块

     

2014-04-08 14:43:16.476 dispex [4346:60b]第6块补充

     

2014-04-08 14:43:16.477 dispex [4346:60b] block 6

     

2014-04-08 14:43:16.477 dispex [4346:60b]第7块补充

     

2014-04-08 14:43:16.477 dispex [4346:60b]第7块

     

2014-04-08 14:43:16.477 dispex [4346:60b]第8块补充

     

2014-04-08 14:43:16.478 dispex [4346:60b] block 8

     

2014-04-08 14:43:16.478 dispex [4346:60b]第9块补充

     

2014-04-08 14:43:16.478 dispex [4346:60b]第9块

     

2014-04-08 14:43:16.479 dispex [4346:60b]第10块补充

     

2014-04-08 14:43:16.479 dispex [4346:60b]第10块

     

2014-04-08 14:43:16.479 dispex [4346:60b]所有积木都加入了队列    - >功能返回

在此示例中,我们使用dispatch_sync函数和串行队列。很容易看出,当前一个块完成执行时,所有块都被添加。这是dispatch_sync的特征。换句话说,函数不会返回,直到执行块结束。由于这是一个串行队列,因此这里的顺序也得到了尊重。

下一步:

/* Dispatch async with concurrent queue */
NSLog(@"\n\nDISPATCH: Async - QUEUE: Concurrent");
dispatch_group_t group_async_concurrent = dispatch_group_create();

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 1");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 2");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 3");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 4");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 5");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 6");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 7");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 8");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 9");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 10");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 11");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 12");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 13");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 14");
});

NSLog(@"ALL BLOCK ADDED TO THE QUEUE --> FUNCTION RETURNED");
  

DISPATCH:Async - QUEUE:Concurrent

     

2014-04-08 14:43:16.480 dispex [4346:60b]所有积木都加入了队列    - >功能返回

     

2014-04-08 14:43:16.480 dispex [4346:1303]第1块

     

2014-04-08 14:43:16.480 dispex [4346:3503]第2块

     

2014-04-08 14:43:16.480 dispex [4346:3603]第3块

     

2014-04-08 14:43:16.480 dispex [4346:3803]第5块

     

2014-04-08 14:43:16.480 dispex [4346:3703]第4块

     

2014-04-08 14:43:16.480 dispex [4346:3903]第6块

     

2014-04-08 14:43:16.480 dispex [4346:3a03]第7块

     

2014-04-08 14:43:16.480 dispex [4346:3b03]第8块

     

2014-04-08 14:43:16.482 dispex [4346:1303]第9块

     

2014-04-08 14:43:16.483 dispex [4346:3503]第10块

     

2014-04-08 14:43:16.483 dispex [4346:3803]第12块

     

2014-04-08 14:43:16.483 dispex [4346:3703]第13块

     

2014-04-08 14:43:16.483 dispex [4346:3903]第14块

     

2014-04-08 14:43:16.483 dispex [4346:3603]第11块

正如我之前所说的,这里我展示了如何工作dispatch_async但是并发队列。 这非常有趣,因为如果没有NSLog显示何时添加块,您可以看到在执行第一个块之前如何添加所有块。此行为不是常量可能会执行block1并在dispatch_async完成后立即将所有块添加到队列中,然后继续执行其他块。另外需要注意的是,块是同时执行的,因此它们并不尊重添加的顺序,而且这种行为不是恒定的,而是取决于CPU的使用,性能和许多其他因素。

下一步:

/* Just wait before begin with the next test */
dispatch_group_wait(group_async_concurrent, DISPATCH_TIME_FOREVER);


/* Dispatch sync with concurrent queue */
NSLog(@"\n\nDISPATCH: Sync - QUEUE: Concurrent");

NSLog(@"block 1 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 1");
});

NSLog(@"block 2 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 2");
});

NSLog(@"block 3 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 3");
});

NSLog(@"block 4 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 4");
});

NSLog(@"block 5 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 5");
});

NSLog(@"block 6 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 6");
});

NSLog(@"block 7 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 7");
});

NSLog(@"block 8 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 8");
});

NSLog(@"block 9 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 9");
});

NSLog(@"block 10 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 10");
});

NSLog(@"ALL BLOCK ADDED TO THE QUEUE --> FUNCTION RETURNED");
  

DISPATCH:Sync - QUEUE:Concurrent

     

2014-04-08 14:43:16.486 dispex [4346:60b]第1块补充

     

2014-04-08 14:43:16.486 dispex [4346:60b] block 1

     

2014-04-08 14:43:16.487 dispex [4346:60b]第2块补充

     

2014-04-08 14:43:16.487 dispex [4346:60b] block 2

     

2014-04-08 14:43:16.487 dispex [4346:60b]第3块补充

     

2014-04-08 14:43:16.488 dispex [4346:60b] block 3

     

2014-04-08 14:43:16.488 dispex [4346:60b]第4块补充

     

2014-04-08 14:43:16.488 dispex [4346:60b] block 4

     

2014-04-08 14:43:16.489 dispex [4346:60b]第5块补充

     

2014-04-08 14:43:16.489 dispex [4346:60b]第5块

     

2014-04-08 14:43:16.489 dispex [4346:60b]第6块补充

     

2014-04-08 14:43:16.489 dispex [4346:60b] block 6

     

2014-04-08 14:43:16.490 dispex [4346:60b]第7块补充

     

2014-04-08 14:43:16.490 dispex [4346:60b]第7块

     

2014-04-08 14:43:16.490 dispex [4346:60b]第8块补充

     

2014-04-08 14:43:16.491 dispex [4346:60b] block 8

     

2014-04-08 14:43:16.491 dispex [4346:60b]第9块补充

     

2014-04-08 14:43:16.491 dispex [4346:60b]第9块

     

2014-04-08 14:43:16.492 dispex [4346:60b]第10块补充

     

2014-04-08 14:43:16.492 dispex [4346:60b]第10块

     

2014-04-08 14:43:16.492 dispex [4346:60b]所有积木都加入了队列    - >功能返回

最后,我们将dispatch_sync并发队列一起使用。它似乎完全等同于夫妻同步/串行。在这种情况下是如此。这种行为的原因在于,如果队列是并发的,它还没有其他块执行,因为我们正在使用同步调度程序,所以它等待添加下一个块,直到实际没有完成要执行。如果我们还要添加dispatch_async的块,那么这种类型的对( sync / concurrent )非常有用。在这种情况下,调度程序可以将其他块添加到要执行的队列中。

希望这个迷你演示有用;)

干杯!