Arrays in Swift are not thread safe. What would happen when you access them concurrently is undefined. So some elements not being added, or the wrong elements being added, or your program crashing, are all possible results from running the code.
Changing to sync
doesn't help, because you are still posting work on a concurrent queue, which will run them concurrently, when you post work concurrently on it using concurrentPerform
.
What sync
guarantees is that it returns after the work completes, so that the code after it runs after the work is done. For example, if you have an extra print
after sync
:
queue.sync {
print(i)
let last = numbers.last ?? 0
numbers.append(last + 1)
}
print("Foo")
Foo
is guaranteed to be printed after numbers.append(last + 1)
.
See also this guide.
So to achieve [1,2,3,4,5,6,7,8,9,10]
, you should post the work on a serial queue, which guarantees that the work will be executed sequentially. Alternatively, if you only have a concurrent queue, use the .barrier
flag:
queue.async(flags: .barrier) {
Also, if what you actually meant is for concurrentPerform
to use queue
to do the "concurrent performing", then as this post says, you should do it like this:
queue.async {
DispatchQueue.concurrentPerform(iterations: 10) { i in
print(i)
someSerialQueue.async {
let last = numbers.last ?? 0
numbers.append(last + 1)
}
}
}