【发布时间】:2023-03-07 22:38:02
【问题描述】:
我假设我知道如何使用 DispatchGroup,为了理解这个问题,我已经尝试过:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
performUsingGroup()
}
func performUsingGroup() {
let dq1 = DispatchQueue.global(qos: .userInitiated)
let dq2 = DispatchQueue.global(qos: .userInitiated)
let group = DispatchGroup()
group.enter()
dq1.async {
for i in 1...3 {
print("\(#function) DispatchQueue 1: \(i)")
}
group.leave()
}
group.wait()
dq2.async {
for i in 1...3 {
print("\(#function) DispatchQueue 2: \(i)")
}
}
group.notify(queue: DispatchQueue.main) {
print("done by group")
}
}
}
结果——正如预期的那样——是:
performUsingGroup() DispatchQueue 1: 1
performUsingGroup() DispatchQueue 1: 2
performUsingGroup() DispatchQueue 1: 3
performUsingGroup() DispatchQueue 2: 1
performUsingGroup() DispatchQueue 2: 2
performUsingGroup() DispatchQueue 2: 3
done by group
为了使用信号量,我实现了:
func performUsingSemaphore() {
let dq1 = DispatchQueue.global(qos: .userInitiated)
let dq2 = DispatchQueue.global(qos: .userInitiated)
let semaphore = DispatchSemaphore(value: 1)
dq1.async {
semaphore.wait()
for i in 1...3 {
print("\(#function) DispatchQueue 1: \(i)")
}
semaphore.signal()
}
dq2.async {
semaphore.wait()
for i in 1...3 {
print("\(#function) DispatchQueue 2: \(i)")
}
semaphore.signal()
}
}
并在viewDidLoad 方法中调用它。结果是:
performUsingSemaphore() DispatchQueue 1: 1
performUsingSemaphore() DispatchQueue 1: 2
performUsingSemaphore() DispatchQueue 1: 3
performUsingSemaphore() DispatchQueue 2: 1
performUsingSemaphore() DispatchQueue 2: 2
performUsingSemaphore() DispatchQueue 2: 3
从概念上讲,DispachGroup 和 Semaphore 都服务于相同的目的(除非我误解了什么)。
老实说,我不熟悉:何时使用 Semaphore,尤其是在与 DispachGroup 合作时 - 可能 - 处理该问题。
我缺少什么?
【问题讨论】:
-
信号量可用于各种应用程序。但是对于这样的任务,任何调用
wait(无论是信号量还是组)通常都是一个坏主意。当你这样做时你正在阻塞一个线程(更糟糕的是,如果你阻塞了主线程,那可能会导致严重的问题)。使用调度组notify或类似模式几乎总是更好。拥抱异步模式而不是使用wait来实现同步行为。 -
我想在信号量的情况下,理论上
dq2有可能在dq1之前运行,在这种情况下,执行顺序不能保证(与DispatchGroup不同)。任何人都可以确认/纠正吗? -
@GuyKogus -
dq1与dq2的潜在时机与信号量无关。事实是(a)有两个单独的队列,(b)他正在做async。 -
我刚刚在 Playgrounds 中做了一个快速测试,
DispatchQueue.global(qos: .userInitiated)将返回相同的队列。因此,在这种情况下,如果该队列是串行的,则信号量将不会做任何事情。除非该代码只是一个示例,我们应该想象它们是唯一的队列。 -
@GuyKogus "如果该队列是串行的" ...全局队列不是串行的。
标签: ios swift grand-central-dispatch semaphore