返回

GCD(二)dispatch_barrier, 为并发队列引入顺序

IOS

问题:并发队列与FIFO顺序

正如上一篇文章讲到的,并发队列允许你追加到队列的block并发执行。但是这也带来了一个问题,那就是并发队列中的block执行顺序与入队的顺序并不相同,这显然与我们对队列的传统理解相悖。

举个例子,假设我们有一个并发队列,然后我们向这个队列中追加了三个任务,任务A、B、C。按照FIFO的顺序,任务A应该先执行,任务B其次,任务C最后执行。

但是,由于并发队列允许任务并发执行,因此任务A、B、C有可能同时执行,甚至可能任务C先执行,任务A后执行。

解决方案:dispatch_barrier

为了解决并发队列中的顺序问题,GCD提供了dispatch_barrier方法。dispatch_barrier是一个特殊的方法,它可以将任务添加到队列中,并确保在该任务执行之前,队列中的所有其他任务都已执行完毕。

使用dispatch_barrier方法很简单,你只需要在你想确保执行顺序的任务之前调用它即可。例如,在上面的例子中,如果你想确保任务A在任务B和任务C之前执行,你可以使用dispatch_barrier方法如下:

dispatch_async(queue, ^{
    // 任务A
});

dispatch_barrier_async(queue, ^{
    // 任务B
});

dispatch_async(queue, ^{
    // 任务C
});

在上面的代码中,我们首先使用dispatch_async方法将任务A添加到队列中。然后,我们使用dispatch_barrier_async方法将任务B添加到队列中。最后,我们使用dispatch_async方法将任务C添加到队列中。

通过使用dispatch_barrier方法,我们可以确保任务A在任务B和任务C之前执行。

dispatch_barrier_sync

dispatch_barrier_sync方法与dispatch_barrier_async方法类似,但它是一个同步方法。这意味着,在dispatch_barrier_sync方法返回之前,队列中的所有其他任务都必须执行完毕。

使用dispatch_barrier_sync方法也很简单,你只需要在你想确保执行顺序的任务之前调用它即可。例如,在上面的例子中,如果你想确保任务A在任务B和任务C之前执行,你可以使用dispatch_barrier_sync方法如下:

dispatch_async(queue, ^{
    // 任务A
});

dispatch_barrier_sync(queue, ^{
    // 任务B
});

dispatch_async(queue, ^{
    // 任务C
});

在上面的代码中,我们首先使用dispatch_async方法将任务A添加到队列中。然后,我们使用dispatch_barrier_sync方法将任务B添加到队列中。最后,我们使用dispatch_async方法将任务C添加到队列中。

通过使用dispatch_barrier_sync方法,我们可以确保任务A在任务B和任务C之前执行,并且在任务B执行之前,当前线程将被阻塞。

使用场景

dispatch_barrier方法可以用于多种场景,例如:

  • 当你想要确保某个任务在其他任务之前执行时。
  • 当你想要将数据从一个线程传输到另一个线程时。
  • 当你想要在多个线程之间同步数据时。

总结

dispatch_barrier方法是一个非常有用的工具,它可以帮助你解决并发队列中的顺序问题。通过使用dispatch_barrier方法,你可以确保在某个任务执行之前,队列中的所有其他任务都已执行完毕。