GCD 串行异步队列与嵌套在异步中的串行同步队列

GCD serial async queue vs serial sync queue nested in async

我必须保护代码的关键部分。 我不希望调用者被可能耗时的函数阻塞,所以我创建了一个带有后台 qos 的串行队列,然后异步调度:

private let someQueue = DispatchQueue(label: "\(type(of: self)).someQueue", qos: .background)

func doSomething() {
    self.someQueue.async { 
       //critical section
    }
}

根据我的理解,该函数将直接 return 在调用线程上而不阻塞。 我还看到某个地方首先在全局队列上异步调度,然后在串行队列上同步调度:

private let someQueue2 = DispatchQueue(label: "\(type(of: self)).someQueue2")

func doSomething() {
    DispatchQueue.global(qos: .background).async {
        self.someQueue2.sync { 
           //critical section
         }
    }
}

这两种方法有什么区别? 哪种方法正确?

在第一种方法中,调用线程不会被阻塞,异步块中传递的任务(临界区)将在后台执行。

在第二种方法中,调用线程未被阻塞,但“后台”线程将等待另一个线程执行的同步块(临界区)执行。

我不知道你在关键部分做了什么,但似乎第一种方法似乎是最好的方法。请注意,后台 qos 非常慢,可以为您的队列使用默认 qos,除非您知道自己在做什么。另请注意,约定要求您使用包标识符作为队列的标签。所以像这样:

private let someQueue = DispatchQueue(label: "\(Bundle.main.bundleIdentifier ?? "").\(type(of: self)).someQueue")