bcl*_*mer 6 multithreading grand-central-dispatch ios swift
我最近一直在试验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")
}
}
}
Run Code Online (Sandbox Code Playgroud)
我希望它能打印出来
Finished a default
Finished a high
// Repeat default and high alternating back and forth 1000 times (because there are 1000 loops)
Run Code Online (Sandbox Code Playgroud)
但实际发生的是打印的日志
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
Run Code Online (Sandbox Code Playgroud)
它在一开始就有意义,交替一点点.连续21个默认值都有一定意义.但是它在没有处理单个高块的情况下执行977个默认块.我认为这种情况正在发生,因为调度员正忙于处理其他所有事情.但是,它仍然是高优先级队列与默认优先级队列.
有没有人对正在发生的事情有任何见解?
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")
Run Code Online (Sandbox Code Playgroud)
在这里,我希望在打印之前执行几个defaults和几个highs Done Dispatching Everything,然后执行所有highs然后执行所有defaults.
但是,结果如下:
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
Run Code Online (Sandbox Code Playgroud)
所以正在发生的事情是,即使在安排了所有事情之后,default发生的事情也远不止于此high.然后在所有defaults完成之后,highs终于开始执行并大量完成.
另一块
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")
Run Code Online (Sandbox Code Playgroud)
结果让我大吃一惊.它与我的第二个例子(编辑1)完全相同.即使highs都在s之前安排default,它仍然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")
}
}
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")
Run Code Online (Sandbox Code Playgroud)
这完全按预期执行.所有的highs运行,然后所有backgrounds运行,没有任何例外.然而,这在执行上与编辑2有很大不同,但理论上应该完全相同.
检查https://en.wikipedia.org/wiki/Priority_inversion
不要打印到标准输出(将所有打印分派到某个低优先级串行队列)并再次检查所有结果。
在你的游乐场试试这个
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")
Run Code Online (Sandbox Code Playgroud)
它应该打印(不要期望相同!!)更真实的东西
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
Run Code Online (Sandbox Code Playgroud)