任务可以在串行队列上异步执行吗?

时间:2021-06-15 18:37:17

标签: asynchronous synchronization grand-central-dispatch

我想了解 GCD 中串行队列和并发队列的基本功能。

我们可以在并发队列上执行同步操作吗?据我所知,同步意味着一个接一个地执行任务,但是并行执行任务的并发队列怎么可能呢?这对我来说似乎是矛盾的。

同理,如何在串行队列上执行异步操作,因为串行队列一个接一个执行任务,如何并发执行?

如果有人能用图片来解释,那就很清楚了。

1 个答案:

答案 0 :(得分:0)

你问:

<块引用>

我们可以在并发队列上执行同步操作吗?据我所知,同步意味着一个接一个地执行任务,但是并行执行任务的并发队列怎么可能呢?

好的,在回答您的问题之前,让我们先考虑一下术语:

什么是“同步操作”?它会在该操作期间阻塞其各自的线程。但是并发队列可以使用多个线程同时在同一个队列上执行这些单独的同步操作,每个线程都运行在自己的线程上。

让我们举一个实际的例子:考虑一个同步操作,它可能是一种处理图像的算法(例如调整图像大小或将彩色图像转换为黑白图像)。当你执行这个操作时,一般会占用各自的线程,直到操作完成。

因此,鉴于该示例,是的,您当然可以(而且我们经常这样做)并行执行多个并发同步操作。使用我们之前的示例,您可能有 4 个要同时处理的图像。因此,您可以实例化一个并发队列,并将这四个操作添加到该队列中,它们将并行处理,每个操作都在自己的“工作线程”上进行。

然后你问:

<块引用>

同理,如何在串行队列上执行异步操作,因为串行队列一个接一个执行任务,如何并发执行?

这在一定程度上取决于您所说的“操作”是什么意思。您是在谈论“操作队列”上的 Swift Operation(或 Objective-C NSOperation)吗?或者您是否更广泛地使用术语“操作”,因为它适用于 GCD 和调度队列?

我问的原因是,在 GCD(又名“调度队列”)的世界中,您根本不会“对串行队列执行异步操作”。您从串行队列启动异步任务,但“异步”的定义意味着当前线程不等待任务完成(这通常意味着,通常在幕后,另一个队列/线程正在做这项工作)。

一个很好的例子是当您从串行队列启动一系列网络请求时。隐藏在 NSURLSession/URLSession 中,它有自己的队列/线程同时管理这些多个网络请求。如果您不希望这些请求同时运行,则需要一些技巧来采用专为并发操作而设计的 API 并使其按顺序运行,一个接一个。

这是操作队列发挥作用的地方,因为它们确实具有自定义 Operation/NSOperation 子类的概念,您可以在其中定义一个操作来包装异步任务,这样在异步任务完成之前操作不会“完成”。它使用 KVO 在操作正在执行、完成等时通知队列。在这种情况下,您可以定义一个串行操作队列(即,maxConcurrentOperationCount 为 {{ 1}}),将一系列您自己的异步操作子类实例添加到该队列中,并且它可以依次运行它们,一个接一个。但是将操作队列与异步操作一起使用可能有点复杂。如果这确实是您想要做的,我们可以为您提供一些示例。但是,为了全面公开,这种操作队列模式现在使用频率较低,您经常会看到其他模式(例如组合)或新的 async-await API 来实现类似的结果。

因此,如果没有更详细地了解“串行队列上的异步操作”的确切含义,我们就无法回答后一个问题。给我们一个实际示例,说明您的意思(以及您使用的 API)。

相关问题