【问题标题】:Sync dispatch on current queue在当前队列上同步调度
【发布时间】:2013-10-11 10:02:59
【问题描述】:

我知道您可能会觉得这是一个奇怪的问题,但我只是在学习 GCD,我想完全了解它的所有方面。所以这里是:

是否有任何理由在 CURRENT QUEUE 上调度任务 SYNC?

例如:

    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(...);
    dispatch_async(concurrentQueue, ^{
       //this is work task 0

       //first do something here, then suddenly:

       dispatch_sync(concurrentQueue, ^{
               //work task 1
       });

       //continue work task 0
    });

我了解一件事:如果我使用 serial 队列而不是 concurrentQueue,那么我会在该串行队列上陷入死锁,因为 work task 1work task 0 完成之前无法启动(因为保证执行顺序的串行队列),同时work task 0 无法继续执行,因为它等待 SYNC dispath 函数返回(如果我错了请纠正我,那会让我总菜鸟)。

所以回到最初的想法,上面的代码和相同的代码之间有什么区别,而不是直接调用dispatch_sync 函数,而是直接编写work task 1 代码?

【问题讨论】:

    标签: ios multithreading concurrency grand-central-dispatch


    【解决方案1】:

    假设所有示例都使用此队列:

    dispatch_queue_t queue = dispatch_queue_create(“com.somecompany.queue”, nil);

    情况 1 - 正常

    dispatch_async(queue, ^{
        [self goDoSomethingLongAndInvolved];
        dispatch_async(queue, ^{
            NSLog(@"Situation 1");
        });
    });
    

    情况 2 - 不行!死锁!

    dispatch_sync(queue, ^{
        [self goDoSomethingLongAndInvolved];
        dispatch_sync(queue, ^{
            NSLog(@"Situation 2”); // NOT REACHED!  DEADLOCK!
        });
    });
    

    情况 3 - 不行!死锁!

    dispatch_async(queue, ^{
        [self goDoSomethingLongAndInvolved];
        dispatch_sync(queue, ^{
            NSLog(@"Situation 3"); // NOT REACHED!  DEADLOCK!
        });
    });
    

    情况 4 - 正常

    dispatch_sync(queue, ^{
        [self goDoSomethingLongAndInvolved];
        dispatch_async(queue, ^{
            NSLog(@"Situation 4");
        });
    });
    

    基本上dispatch_sync不喜欢在里面。

    只有 dispatch_asyncs 可以进去。

    【讨论】:

      【解决方案2】:

      没有。我想不出任何理由让dispatch_sync 出现在你已经在同一个并发队列上。如果你这样做,GCD 将立即在同一个线程上直接调用你的块,就像你直接调用它一样。 (我检查过。)正如你所指出的,在串行队列上这样做会让你死锁。

      【讨论】:

      • 我正在拼命地抓住,但是如果您确实希望某个特定任务发生在某个队列上,但发出任务可能会或可能不会发生在该队列上呢?唯一的问题是提出一个队列并发的现实场景。
      • @Tommy 问题是:dispatch_sync 到同一个队列是多余的吗?您的问题似乎是,是否有一点将 dispatch_sync 指向可能与当前队列不同的并发队列?是的,如果您希望下一行代码发生在您的 dispatch_sync 代码之后。一个现实的场景是:队列的复杂层次结构和/或重定向队列的代码(因为您的块可以在任何地方结束)。
      • @Jano 你没有理解我的评论。它与 ipmcc 的回答有关,所以我回答的是“我想不出任何理由在你已经在同一个并发队列上进行 dispatch_sync ”,而不是最初的问题。一个原因可能是:您肯定希望在该队列上完成任务。你不知道你是否已经开始了。是的,您可以编写代码来检查这一点,但您只是在复制 Apple 已经编写的代码,所以有一个很好的理由不这样做。
      • @Tommy 您需要注意这一点:如果您确定要在 (Q1) 上完成任务的队列是并发的,那么您可以这样做。但是如果你不知道你当前在哪个队列上执行(Q?),你可能不知道 Q1 是否是并发的。如果它是连续的,并且碰巧 Q1 == Q?,那么dispatch_sync'ing 会让你陷入僵局。您也许可以使用 dispatch_queue_[get|set]_specificdispatch_get_specific 来解决这个问题,但前提是没有其他人使用该功能来处理您要破坏的任何事情。
      • @ipmcc 我绝对同意。而且,为了记录,我想到的唯一一个人为的情况涉及希望以DISPATCH_QUEUE_PRIORITY_LOW 发送进一步工作但不知道自己的优先级的全局队列之一。也许您有一个 Web 服务,它涉及昂贵的解析,然后记账以存储以供重用。解析看起来总是一样的,但是您将其发送为DISPATCH_QUEUE_PRIORITY_HIGHDISPATCH_QUEUE_PRIORITY_LOW,具体取决于它是用于现在还是将来的用户界面。你总是把记账作为低优先级。
      猜你喜欢
      • 2013-07-02
      • 2021-10-24
      • 2011-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多