gpt4 book ai didi

ios - GCD 优先级的意外结果

转载 作者:搜寻专家 更新时间:2023-10-30 22:18:35 25 4
gpt4 key购买 nike

我最近一直在试验 GCD 优先级。这是我一直在使用的代码片段。

for _ in 1...1000 {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
for _ in 1...10000000 {
let _ = sin(0.64739812)
}
print("Finished a default")
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
for _ in 1...10000 {
let _ = sin(0.64739812)
}
print("Finished a high")
}
}
}

我希望它能打印出来

Finished a default
Finished a high
// Repeat default and high alternating back and forth 1000 times (because there are 1000 loops)

但实际发生的是打印的日志

Finished a default
Finished a high
Finished a default x 21
Finished a high
Finished a default
Finished a high x 20
Finished a default x 977
Finished a high x 978

一开始是有道理的,交替一点。即使连续 21 个违约也有一定的道理。但是随后它执行了 977 个默认 block 而不处理单个高 block 。我认为发生这种情况是因为调度员正忙于处理其他所有事情。但是,与默认优先级队列相比,它仍然是一个高优先级队列。

有人知道发生了什么事吗?

编辑 1

for _ in 1...1000 {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
print("Starting a default")
for i in 1...10000000 {
let _ = sin(Double(i))
}
print("Finished a default")
}
}
for _ in 1...1000 {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
print("Starting a high")
for i in 1...10000000 {
let _ = sin(Double(i))
}
print("Finished a high")
}
}

print("Done Dispatching Everything")

在这里,我希望在打印Done Dispatching Everything 之前执行几个default 和几个high,然后执行所有high 然后是所有 default

然而,这是结果:

Starting a default x6
Done Dispatching Everything // at this point, all the high and default blocks have been successfully submitted for execution.
Starting a high
Finished a default
Starting a default
Finished a default
Starting a default
Finished a default
Starting a default
Finished a default
Starting a default
Finished a default
Starting a default
Finished a default
Starting a default
Finished a default
Starting a default
Finished a high
Starting a high
Finished a default
Starting a default
Finished a default
Finished a default
Starting a default
Starting a default
Finished a default
Starting a default
Finished a default
Starting a default
Finished a default
Starting a default
Finished a high
Starting a high
Finished a default
Starting a default
Finished a default
Starting a default
// A sequence that looks like the above for around 1500 lines.
Started+Finished a high x ~500

所以发生的事情是,即使在一切都安排好之后,default 的发生率明显高于 high。然后在所有 default 完成后,high 终于开始执行并批量完成。

编辑2

另一个街区

for _ in 1...1000 {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
print("Starting a high")
for i in 1...10000000 {
let _ = sin(Double(i))
}
print("Finished a high")
}
}
for _ in 1...1000 {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
print("Starting a default")
for i in 1...10000000 {
let _ = sin(Double(i))
}
print("Finished a default")
}
}

print("Done Dispatching Everything")

结果让我大吃一惊。它与我的第二个示例(编辑 1)完全相同。即使 high 都在 default 之前被调度,它仍然会先执行 default block !

编辑3

最后一个例子,我保证

for _ in 1...1000 {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
print("Starting a high")
for i in 1...10000000 {
let _ = sin(Double(i))
}
print("Finished a high")
}
}
for _ in 1...1000 {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) {
print("Starting a background")
for i in 1...10000000 {
let _ = sin(Double(i))
}
print("Finished a background")
}
}

print("Done Dispatching Everything")

这完全按照预期执行。所有 high 运行,然后所有 background 运行,没有任何异常(exception)。然而,这在执行上与编辑 2 有很大不同,但理论上应该完全相同。

最佳答案

检查 https://en.wikipedia.org/wiki/Priority_inversion

不要打印到标准输出(将所有打印发送到一些低优先级串行队列)并再次检查所有结果。

在你的 Playground 试试这个

import Dispatch

let pq = DispatchQueue(label: "print", qos: .background)
let g = DispatchGroup()
func dprint(_ items: Any...) {
pq.async(group: g) {
var r = items.map{ String(describing: $0) }.joined(separator: " ")
print(r)
}
}

let q1 = DispatchQueue(label: "q1", qos: .background, attributes: .concurrent)
let q2 = DispatchQueue(label: "q2", qos: .userInteractive, attributes: .concurrent)

for i in 0..<10 {
q1.async(group: g) {
dprint("q1", i, "started")
for i in 0..<100 {
_ = sin(Double(i))
}
dprint("q1", i, "finished")
}
}
for i in 0..<10 {
q2.async(group: g) {
dprint("\tq2", i, "started")
for i in 0..<100 {
_ = sin(Double(i))
}
dprint("\tq2", i, "finished")
}
}
g.wait()
print("end of test")

它应该打印(不要期望相同!!)更真实的东西

q1 0 started
q1 1 started
q1 2 started
q2 0 started
q2 1 started
q2 2 started
q2 3 started
q2 0 finished
q2 4 started
q2 1 finished
q2 2 finished
q2 5 started
q2 6 started
q2 3 finished
q2 7 started
q2 6 finished
q2 8 started
q2 5 finished
q2 7 finished
q2 4 finished
q2 9 started
q2 8 finished
q2 9 finished
q1 2 finished
q1 3 started
q1 0 finished
q1 4 started
q1 1 finished
q1 6 started
q1 5 started
q1 4 finished
q1 6 finished
q1 7 started
q1 8 started
q1 5 finished
q1 3 finished
q1 9 started
q1 7 finished
q1 8 finished
q1 9 finished
end of test

关于ios - GCD 优先级的意外结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39235046/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com