并发队列中的DispatchQueue同步与同步屏障

时间:2019-10-04 12:09:26

标签: swift concurrency grand-central-dispatch shared-memory

我正经历DispatchQueue障碍,并注意到sync(flags: .barrier)DispatchQueue.global().sync { } 有两种方式

我了解异步屏障的用法,但与同步屏障相混淆。

我也很困惑,我想要做的任务也可以用这个来完成

DispatchQueue.global().sync(flags: .barrier) {

}

那么同步屏障的用途是什么?为什么使用它们?以及这有何不同。

{{1}}

3 个答案:

答案 0 :(得分:4)

在分配屏障同步任务之前分配的任务(同步/异步)将首先完成。然后,屏障同步任务将被专门执行,并且由于它是同步任务,其他任务直到完成为止都不会开始。

具有屏障/非屏障同步和异步的并发队列示例。

let dispatchQueueA = DispatchQueue(label: "A", attributes: .concurrent)

dispatchQueueA.async { // Task1
    for index in 0 ..< 5 {
        sleep(2)
        print("Task 1 - async \(index)")
    }
}

dispatchQueueA.sync { // Task2
    for index in 0 ..< 5 {
        sleep(1)
        print("Task 2 - sync without barrier \(index)")
    }
}

dispatchQueueA.sync(flags: .barrier) { // Task3
    // the tasks(sync, async) assigned before this block will be completed first
    // then this task will execute and as it is sync task no other task will start until it finishes
    for index in 0 ..< 5 {
        sleep(1)
        print("Task 3 - sync with barrier \(index)")
    }
}

dispatchQueueA.async { // Task4
    for index in 5 ..< 10 {
        sleep(1)
        print("Task 4 - async \(index)")
    }
}

dispatchQueueA.sync { // Task5
    for index in 5 ..< 10 {
        sleep(1)
        print("Task 5 - sync without barrier \(index)")
    }
}

上述代码的输出-完成 Task1 Task2 后执行的 Task3(同步屏障)。完成 Task3(同步屏障)后,已启动下一个分配的任务(Task4,Task5)。

Task 2 - sync without barrier 0
Task 1 - async 0
Task 2 - sync without barrier 1
Task 2 - sync without barrier 2
Task 2 - sync without barrier 3
Task 1 - async 1
Task 2 - sync without barrier 4
Task 1 - async 2
Task 1 - async 3
Task 1 - async 4
Task 3 - sync with barrier 0
Task 3 - sync with barrier 1
Task 3 - sync with barrier 2
Task 3 - sync with barrier 3
Task 3 - sync with barrier 4
Task 5 - sync without barrier 5
Task 4 - async 5
Task 5 - sync without barrier 6
Task 4 - async 6
Task 5 - sync without barrier 7
Task 4 - async 7
Task 5 - sync without barrier 8
Task 4 - async 8
Task 5 - sync without barrier 9
Task 4 - async 9

答案 1 :(得分:3)

这里有两件事要考虑:

Sync / Asyc 确定提交队列上的程序流:使用sync()导致提交队列上的执行被阻塞,直到任务完成为止;相反,使用async()不会阻止。

但是,使用标志.barrier ,会影响块在提交到它们的队列中的执行方式(显然,这仅对并发队列有所不同):

使用此标志提交的块将充当屏障:屏障之前 提交的所有其他块将完成,然后屏障块才会执行。在屏障完成后 提交的所有块都不会启动。

答案 2 :(得分:3)

Lutz says(+1),sync / async和障碍是两个完全不同的问题。 sync / async规定了调用线程的行为(即是否等待)。障碍决定了将其派发到的队列的行为(是否允许它与该队列中的任何其他派发的块同时运行)。

但是请注意,障碍不适用于全局队列;它们只会影响您创建的私有并发队列。关于障碍的docs say

  

您指定的队列应该是您自己创建的并发队列...如果传递给此函数的队列是串行队列或全局并发队列之一,则此函数的行为[好像是在没有调度的情况下调度的。障碍]。