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

Ios 调度队列是串行队列,那么为什么它甚至存在于多任务概念中呢?,ios,multithreading,grand-central-dispatch,multitasking,nsthread,Ios,Multithreading,Grand Central Dispatch,Multitasking,Nsthread,我是iPhone开发的新手,正在学习多线程的GCD概念 “dispatch_queue_t”创建了一个串行队列,我读到串行队列一次只执行一个作业。GCD旨在同时执行多个任务,那么为什么串行队列甚至存在呢 例如,我想做两个任务。任务A和任务B。我创建一个串行队列来执行这两个任务。我在排队等候。下面是我正在做的代码: dispatch_queue_t my_serial_queue = dispatch_queue_create("queue_identifier", 0); dispat

我是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\u sync'调用而不是'dispatch\u async'调用。但是,当我在不同的队列中运行这两个任务时,它们不应该同时执行吗?如果不是,那么我们为什么要创建不同的队列?我可能通过'dispatch\u async'调用使用了相同的队列来同时执行这两个任务


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

您的困惑几乎完全是因为您使用的是dispatch\u sync。dispatch_sync不是一个获取并发执行的工具,它是一个为了安全暂时限制它的工具

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

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

__block void *shared = NULL;
for (;;) {
    dispatch_async(aConcurrentDispatchQueue, ^{
        shared = malloc(128);
        free(shared);
    }
}
这将崩溃,因为最终两个并发执行的块将释放一行中的“共享”。这显然是一个人为的例子,但在实践中,几乎所有共享的可变状态都不能同时更改。串行队列是确保您做到这一点的工具

总结:

  • 当块中的工作是真正独立的、线程安全的、纯计算性的时,继续使用dispatch\u async到并发队列
  • 当您有逻辑上独立的任务(每个任务由多个相关块组成)时,请为每个任务使用串行队列
  • 当您有访问共享可变状态的工作时,在串行队列的dispatch_sync()ed块中执行这些访问,在并发队列中执行其余工作
  • 当您需要执行与UI相关的工作时,根据是否需要等待主队列完成,将\u async或\u sync分派到主队列

    • “调度队列”不会创建任何内容。调度队列是一个调度队列,可以是串行的,也可以是并发的

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

      dispatch_sync在队列上调度一个块,并等待该块完成。显然,这在很大程度上限制了并发性。您几乎应该始终使用dispatch\u async

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


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

      @Catfish\u Man:简而言之,如果我想同时执行两个任务(我提到的),我应该(1)在串行队列中使用“dispatch\u async”,或者(2)为这两个任务创建两个并发队列,而不是通过“dispatch\u queue\t”创建两个队列(因为“dispatch\u queue\t”创建串行队列)@Catfish_Man:假设这两个任务是完全独立的。一个并发队列,或者两个串行队列。串行队列对其上的所有内容进行排序,但与其他所有队列都是并发的。并发队列根本不会对它们进行排序。@Catfish\u-Man:我在第一条评论中提到了两种选择。这些是我想要的解决方案吗?不,我在纠正你。您说过两个并发队列,您想要两个串行队列或一个并发队列。@gnasher729:您的陈述:“当您需要一个接一个地执行各种块时,顺序队列仍然有用,并且它们可以与其他队列中的块并发执行。”为了使之实用,我制作了一个演示,创建了两个串行队列。但这些队列不会同时执行。队列B的块在A的所有块完成执行之前不会执行。我甚至尝试使这两个队列同时运行,但仍然得到了相同的结果。为什么在我发出dispatch\u async调用之前,这些队列不能并发运行?(甚至我创建了并发队列)如果使用dispatch_sync(第一个块)、dispatch_sync(第二个块),那么dispatch_sync本身将等待第一个块完成,而dispatch_sync(第二个块)仅在第一个块完成后执行。如果您这样使用它,那么队列在做什么并不重要。