dispatch_queuet是串行队列,那么为什么它甚至存在于多任务概念中呢



我是iPhone开发的新手,正在学习多线程的GCD概念。

"dispatch_queue_t"创建了一个串行队列,我读到串行队列一次只能执行一个作业。GCD旨在同时执行多个任务,那么为什么存在串行队列呢?

例如,我想做两项任务。任务A和任务B。我创建了一个串行队列来执行这两个任务。我在主要队列中执行此操作。这是我正在做的代码:

dispatch_queue_t my_serial_queue = dispatch_queue_create("queue_identifier", 0);
    dispatch_sync(my_serial_queue, ^{
        NSLog(@"Task 1");
    });
    dispatch_sync(my_serial_queue, ^{
        NSLog(@"Task 2");
    });

现在,根据规则,两个任务都将按照串行队列的方式串行执行,即首先执行任务A,然后在任务A完成后执行任务B。而且它在日志中给了我相同的输出。

所以,我的问题是,如果我想同时执行这两个任务怎么办?如果这个问题的答案是为任务B创建另一个串行队列,那么代码的结构应该是这样的:

dispatch_queue_t my_serial_queue_1 = dispatch_queue_create("queue_identifier_1", 0);
dispatch_queue_t my_serial_queue_2 = dispatch_queue_create("queue_identifier_2", 0);

    dispatch_sync(my_serial_queue_1, ^{
        NSLog(@"Task 1");
    });
    dispatch_sync(my_serial_queue_2, ^{
        NSLog(@"Task 2");
    });

我得到了同样的输出。原因是我使用的是"dispatch_sync"调用,而不是"dispatch_async"调用。但是,当我在不同的队列中运行这两个任务时,它们不应该同时执行吗?如果不是,那么我们为什么要创建一个不同的队列呢?我可能通过"dispatch_async"调用使用了相同的队列来同时执行这两个任务。

我真的需要这个问题的答案,因为在未来设计我的多任务应用程序的结构之前,它会更好地指导我。

您的困惑几乎完全是因为您使用了dispatch_sync。dispatch_sync是而不是一个用于获得并发执行的工具,它是一个为了安全起见临时限制它的工具。

使用dispatch_async后,您可以通过拥有多个队列或使用并发队列来获得并发性。在此上下文中使用串行队列的目的是控制哪些工作是同时完成的。

考虑以下非常愚蠢的例子:

__block void *shared = NULL;
for (;;) {
    dispatch_async(aConcurrentDispatchQueue, ^{
        shared = malloc(128);
        free(shared);
    }
}

这将崩溃,因为最终,两个同时执行的块将在一行中释放"shared"。这显然是一个人为的例子,但在实践中,几乎所有共享的可变状态都不能同时更改。串行队列是确保做到这一点的工具。

总结:

  • 当块中的工作是真正独立的、线程安全的、纯计算的时,继续对并发队列使用dispatch_async
  • 当您有逻辑上独立的任务,每个任务都由几个相关的块组成时,请为每个任务使用串行队列
  • 当您有访问共享可变状态的工作时,请在串行队列上的dispatch_sync()ed块中进行这些访问,其余工作在并发队列中进行
  • 当您需要执行与UI相关的工作时,请将dispatch_asyncdispatch_sync发送到主队列,具体取决于您是否需要等待它完成

'dispatch_queue_t'不会创建任何内容。dispatch_queue_t是一个串行或并发的调度队列。

dispatch_queue_create有两个参数。第二个参数决定它创建的队列是串行队列还是并发队列。但通常您不会自己创建并发队列,而是使用三个现有并发队列中的一个。

dispatch_sync在队列上分派一个块,并等待直到该块完成。很明显,这在很大程度上限制了并发性。您几乎应该始终使用dispatch_async。

顺序队列一次只能执行一个块。很明显,这在很大程度上限制了并发性。当您需要一个接一个地执行各种块时,顺序队列仍然很有用,并且它们可以与其他队列中的块同时执行。

因此,为了最大限度地使用处理器,请在并发队列上使用dispatch_async。并且不需要创建多个并发队列。它是并发的。它可以同时运行任意数量的块。

最新更新