ios - 当同步/异步与串行/并发队列混合时,调度程序如何工作?

标签 ios asynchronous queue synchronization grand-central-dispatch

在 Grand Central Dispatch 中,当使用 serial 时,调度程序如何处理不同的队列( concurrentdispatch_sync )函数和 dispatch_async功能?

最佳答案

首先,我们需要两种类型的队列:一种串行和一种并发:

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函数将我们的 block 添加到队列中:

/* 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] block 1 added

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

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

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

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

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

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

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

2014-04-08 14:43:16.469 dispex[4346:60b] block 5 added

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

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

2014-04-08 14:43:16.471 dispex[4346:60b] block 7 added

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

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

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

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

2014-04-08 14:43:16.471 dispex[4346:60b] block 9 added

2014-04-08 14:43:16.472 dispex[4346:60b] block 10 added

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

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

2014-04-08 14:43:16.472 dispex[4346:60b] ALL BLOCK ADDED TO THE QUEUE --> FUNCTION RETURNED

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

ALL BLOCK ADDED

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

下一个:

/* 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] block 1 added

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

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

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

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

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

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

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

2014-04-08 14:43:16.476 dispex[4346:60b] block 5 added

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

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

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

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

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

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

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

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

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

2014-04-08 14:43:16.479 dispex[4346:60b] block 10 added

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

2014-04-08 14:43:16.479 dispex[4346:60b] ALL BLOCK ADDED TO THE QUEUE --> FUNCTION RETURNED

在此示例中,我们将 dispatch_sync 函数与串行队列结合使用。很容易看出,当前一个 block 执行完毕时,所有 block 都会被添加。这是dispatch_sync的一个特性。换句话说,直到 block 执行完毕后,该函数才会返回。由于这是一个串行队列,因此这里的顺序也受到尊重。

下一个:

/* 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] ALL BLOCK ADDED TO THE QUEUE --> FUNCTION RETURNED

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

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

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

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

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

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

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

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

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

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

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

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

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

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

正如我之前所说,这里我展示了 dispatch_async 如何使用并发队列工作。 这真的很有趣,因为没有 NSLog 显示何时添加 block ,您可以看到在执行第一个 block 之前如何添加所有 block 。这种行为不是恒定的可能会发生 block1 被执行后,在 dispatch_async 完成后立即将所有 block 添加到队列中,然后继续执行其他 block 。另一件需要注意的事情是, block 是并发执行的,因此它们不遵守添加顺序,而且这种行为不是恒定的,而是取决于 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] block 1 added

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

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

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

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

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

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

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

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

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

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

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

2014-04-08 14:43:16.490 dispex[4346:60b] block 7 added

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

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

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

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

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

2014-04-08 14:43:16.492 dispex[4346:60b] block 10 added

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

2014-04-08 14:43:16.492 dispex[4346:60b] ALL BLOCK ADDED TO THE QUEUE --> FUNCTION RETURNED

最后,我们在这里使用了 dispatch_sync并发队列。它看起来完全等于同步/串行对。在这种情况下就是这样。这种行为的原因是,如果队列是并发的,它没有其他 block 要执行,因为我们正在使用同步调度程序,因此它会等待添加下一个 block ,直到实际执行完毕为止。如果我们还使用 dispatch_async 将 block 添加到队列中,这种类型的对(同步/并发)非常有用。在这种情况下,调度程序可以将其他 block 添加到要执行的队列中。

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

干杯!

关于ios - 当同步/异步与串行/并发队列混合时,调度程序如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22940154/

相关文章:

ios - 是否可以缓存 iPhone UIWebView 中加载的资源?

ios - 对象-C : dispatch_async crashes without NSLog

python - 在普通函数中调用异步函数

iOS UIScrollView 双指缩放添加空白

ios - UIButton 不会显示标题

c - 带有空指针的动态数组队列数据结构问题

Python 多线程队列

c - 使用Fedora的C程序出错

android - 如何使 ClipPath 的背景透明?

node.js - NodeJS 代码不等待函数完成