原文地址:https://ali-akhtar.medium.com/concurrency-in-swift-grand-central-dispatch-part-2-1b0b025ee381
这里是Swift并发编程系列
第二篇(共四篇:一)。主要包含Dispatch Group
相关内容。
Dispatch Group
有以下特点:
-
Dispatch Group
可以阻塞线程,等到一个或多个任务完成后继续向下。你可以使用该特性,完成需要等待其他任务完成后才能执行的任务。 - 在分派多个任务来计算一些数据之后,您可以使用
Dispatch Group
来等待这些任务,然后再完成后处理结果,尽管它们也可能运行在不同的队列上。 -
Dispatch Group
可以完成任务的聚合同步
使用wait
如上图,我们做了如下工作:
- 创建了一个标签为“ com.company.app.queue”自定义并发队列
- 创建了一个调度组
- 使用
group.enter()
手动进入组 注意:对此函数的调用必须与group.leave()
平衡,否则应用程序将崩溃 - 通过
queue.async
执行的任务 1 ,它将立即返回并且 GCD 将开始并发运行此任务 - 再次使用
group.enter()
手动已进入组 - 通过
queue.async
执行任务 2,同样,它会立即返回并且 GCD 将开始并发运行此任务 -
group.wait()
将阻塞这里的任何线程,直到所有上述任务都完成为止(所以不要在主线程上使用这个函数),因为我们在主线程上调用了这个方法,它将阻塞主线程。
为了避免阻塞主线程,我们可以在后台线程进行等待,像这样:
使用notify
在上一节,我们使用队列异步派发来避免阻塞主线程,但这看上去并不是最优解。因为它始终会阻塞一个线程。幸运的是,GCD提供了更优的方案,使用notify
你可以在所有任务完成后获得通知:
在下面的例子中,任务1和任务3完成后会打印#3 finished
,但它不会等待任务2完成。因为任务2并没有在group
中执行。
在我们的改造后,#3 finished
会在所有任务执行完成后再输出:
DispatchGroup.notify(qos:flags:queue:execute:)
接收一个参数queue
来决定完成后的任务将在哪个队列执行。若我们指定主队列,它将在主线程执行:
barrier
-
Dispatch barriers
是一组和并发队列
一起工作的函数,提供类似串行
执行任务的功能。 - 当您将DispatchWorkItem(任务)提交到调度队列时,您可以设置标志以指示它应该是特定时间在指定队列上执行的唯一任务。这意味着在
Dispatch barrier
任务之前提交到队列的所有任务必须在它开始执行之前完成。
对于上面的例子:
- 创建一个并发队列
- 异步派发了任务1和任务2
- 此时,上面的两个任务会并发执行。这时我们使用
barrier
作为标志添加任务3,它将在之前的任务全部完成后才开始执行,并且在任务3执行过程中,不会有其他任务执行。 - 继续添加任务4,它将在
barrier
任务之后执行
结果如下:
我们使用barrier
派发的任务在并发队列中独立的以串行
方式执行了。就像下面这样:
读写问题
如果你在多个线程进行读写操作,你一定会碰到读写问题
。而使用Dispatch barrier
可以很好的实现多读单写模型:
1 |
|