【问题标题】:Grand Central Dispatch: What happens when queues get overloaded?Grand Central Dispatch:当队列超载时会发生什么?
【发布时间】:2020-08-24 23:20:24
【问题描述】:

我在 GCD 的文档或教程中没有找到一个非常简单的问题:如果我将工作提交到队列的速度快于处理和删除的速度会怎样?我知道 GCD 队列没有大小限制,在程序内存不足之前会一直工作吗?有没有办法妥善处理这种情况?

【问题讨论】:

    标签: ios swift grand-central-dispatch


    【解决方案1】:

    如果我将工作提交到队列的速度快于处理和删除的速度会怎样?

    视情况而定。

    • 如果将任务分派到单个/共享串行队列,它们只会被添加到队列中,并且会以先进先出的方式处理它们。没问题。内存是你唯一的限制。

    • 但是,如果将任务分派到并发队列,最终会导致“线程爆炸”,并且您将很快耗尽可用于该服务质量 (QoS) 的有限数量的工作线程。如果操作系统需要使用相同 QoS 的队列,这可能会导致不可预知的行为。因此,您必须非常小心避免这种线程爆炸。

      在 WWDC 2015 Building Responsive and Efficient Apps with GCD 和 WWDC 2016 Concurrent Programming With GCD in Swift 3 中再次查看线程爆炸的讨论。

    有没有办法妥善处理这种情况?

    很难在摘要中回答这个问题。不同的情况需要不同的解决方案。

    在线程爆炸的情况下,解决方案是使用concurrentPerform限制并发程度(将并发限制在设备上的核心数)。或者我们使用操作队列及其maxConcurrentOperationCount 将并发程度限制在合理的范围内。还有其他模式,但想法是将并发限制为适合相关设备的东西。

    但是,如果您只是将大量任务分派到串行队列,那么您无能为力(除了寻找并行机会,以有效利用所有 CPU 内核)。但这没关系,因为这是队列的全部目的,让它按照提交的顺序执行任务,即使队列跟不上。如果它不遵循这种先进先出的模式,它就不会是一个“队列”。

    现在,如果处理无法足够快地处理的实时数据,您就会遇到不同的问题。在这种情况下,您可能希望将输入的捕获与处理分离,并决定如何处理它。例如。例如,如果您无法跟上视频的实时处理速度,您可以选择。您要么开始丢帧,要么异步/稍后处理数据。您只需要决定什么适合您的用例。我们无法抽象地回答这个问题。

    【讨论】:

    • 限制并发工作的方法与建议的信号量方法here有何不同?
    • 我是written about that semaphore technique,这就是我在上面写的“还有其他模式”时明确考虑的问题。这只是一种不太直观的模式(许多新开发人员不会立即理解为什么要在 之前等待 信号,为什么要使用非零值等)。它也是更脆弱的方法(例如,一个简单的执行路径,你忘记signal 并且你死锁)。此外,concurrentPerform 针对您的内核数量进行了动态优化,以实现最高效率。但信号量有效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-09
    • 1970-01-01
    • 2012-11-27
    • 2011-07-28
    • 2023-03-25
    • 1970-01-01
    相关资源
    最近更新 更多