DispatchQueue 异步问题
DispatchQueue async issue
var numbers: [Int] = []
var queue = DispatchQueue(label: "myqueue", attributes: .concurrent)
DispatchQueue.concurrentPerform(iterations: 10) { i in
queue.async() {
print(i)
let last = numbers.last ?? 0
numbers.append(last + 1)
}
}
sleep(1)
print(numbers)
输出:
[1, 2, 3, 4, 5] --(可能不同)
异步块中的工作项运行了 10 次,但为什么数组中的数字少于 10 个?
第二个问题,如果我把async改成sync,数字还是小于10,为什么不是[1 2 3 4 5 6 7 8 9 10]?
Swift 中的数组不是线程安全的。当您同时访问它们时会发生什么是不确定的。所以一些元素没有被添加,或者添加了错误的元素,或者你的程序崩溃,都是 运行 宁代码的可能结果。
更改为 sync
没有帮助,因为您仍在 post 处理 并发 队列,这将 运行他们并发,当你 post 使用 concurrentPerform
.
同时处理它时
sync
保证的是它returns工作完成后,使得它后面的代码运行s工作完成后。例如,如果在 sync
之后有一个额外的 print
:
queue.sync {
print(i)
let last = numbers.last ?? 0
numbers.append(last + 1)
}
print("Foo")
Foo
保证在numbers.append(last + 1)
之后打印。
另见 this guide。
所以要实现[1,2,3,4,5,6,7,8,9,10]
,你应该post在一个串行队列上工作,这保证了工作将按顺序执行。或者,如果您只有一个并发队列,请使用 .barrier
标志:
queue.async(flags: .barrier) {
此外,如果您的实际意思是 concurrentPerform
使用 queue
进行“并发执行”,那么正如 所说,您应该这样做:
queue.async {
DispatchQueue.concurrentPerform(iterations: 10) { i in
print(i)
someSerialQueue.async {
let last = numbers.last ?? 0
numbers.append(last + 1)
}
}
}
var numbers: [Int] = []
var queue = DispatchQueue(label: "myqueue", attributes: .concurrent)
DispatchQueue.concurrentPerform(iterations: 10) { i in
queue.async() {
print(i)
let last = numbers.last ?? 0
numbers.append(last + 1)
}
}
sleep(1)
print(numbers)
输出:
[1, 2, 3, 4, 5] --(可能不同)
异步块中的工作项运行了 10 次,但为什么数组中的数字少于 10 个?
第二个问题,如果我把async改成sync,数字还是小于10,为什么不是[1 2 3 4 5 6 7 8 9 10]?
Swift 中的数组不是线程安全的。当您同时访问它们时会发生什么是不确定的。所以一些元素没有被添加,或者添加了错误的元素,或者你的程序崩溃,都是 运行 宁代码的可能结果。
更改为 sync
没有帮助,因为您仍在 post 处理 并发 队列,这将 运行他们并发,当你 post 使用 concurrentPerform
.
sync
保证的是它returns工作完成后,使得它后面的代码运行s工作完成后。例如,如果在 sync
之后有一个额外的 print
:
queue.sync {
print(i)
let last = numbers.last ?? 0
numbers.append(last + 1)
}
print("Foo")
Foo
保证在numbers.append(last + 1)
之后打印。
另见 this guide。
所以要实现[1,2,3,4,5,6,7,8,9,10]
,你应该post在一个串行队列上工作,这保证了工作将按顺序执行。或者,如果您只有一个并发队列,请使用 .barrier
标志:
queue.async(flags: .barrier) {
此外,如果您的实际意思是 concurrentPerform
使用 queue
进行“并发执行”,那么正如
queue.async {
DispatchQueue.concurrentPerform(iterations: 10) { i in
print(i)
someSerialQueue.async {
let last = numbers.last ?? 0
numbers.append(last + 1)
}
}
}